ZQuest Classic Coverage Report


Directory: src/
File: src/zq/zq_tiles.cpp
Date: 2024-10-11 09:26:44
Exec Total Coverage
Lines: 98 7702 1.3%
Functions: 1 199 0.5%
Branches: 14 6713 0.2%

Line Branch Exec Source
1 #include <cstring>
2 #include <cmath>
3
4 #include "base/files.h"
5 #include "base/qrs.h"
6 #include "base/dmap.h"
7 #include "base/cpool.h"
8 #include "base/autocombo.h"
9 #include "base/packfile.h"
10 #include "base/gui.h"
11 #include "base/combo.h"
12 #include "base/msgstr.h"
13 #include "base/zdefs.h"
14 #include "new_subscr.h"
15 #include "subscr.h"
16 #include "zq/zquestdat.h"
17 #include "zq/zq_tiles.h"
18 #include "zq/zquest.h"
19 #include "tiles.h"
20 #include "zq/zq_misc.h"
21 #include "zq/zq_class.h"
22 #include "base/zsys.h"
23 #include "base/colors.h"
24 #include "base/qst.h"
25 #include "gui/jwin.h"
26 #include <base/new_menu.h>
27 #include "base/jwinfsel.h"
28 #include "zc/zc_custom.h"
29 #include "zq/questReport.h"
30 #include "dialog/info.h"
31 #include "dialog/scaletile.h"
32 #include "dialog/rotatetile.h"
33 #include "dialog/alert.h"
34 #include "drawing.h"
35 #include "colorname.h"
36 #include "zq/render.h"
37 #include "zinfo.h"
38 #include <fmt/format.h>
39 #include <functional>
40 #include "zq/moveinfo.h"
41 using std::set;
42
43 extern zcmodule moduledata;
44
45 #ifdef _MSC_VER
46 #define stricmp _stricmp
47 #endif
48
49 #define HIDE_USED (show_only_unused_tiles&1)
50 #define HIDE_UNUSED (show_only_unused_tiles&2)
51 #define HIDE_BLANK (show_only_unused_tiles&4)
52 #define HIDE_8BIT_MARKER (show_only_unused_tiles&8)
53
54 extern void large_dialog(DIALOG *d);
55 static void massRecolorReset4Bit();
56 static void massRecolorReset8Bit();
57 static bool massRecolorSetup(int32_t cset);
58 static void massRecolorApply(int32_t tile);
59 extern int32_t last_droplist_sel;
60 extern int32_t TilePgCursorCol, CmbPgCursorCol;
61
62 int32_t ex=0;
63 int32_t nextcombo_fake_click=0;
64 int32_t invcol=0;
65 int32_t tthighlight = 1;
66 int32_t showcolortip = 1;
67 int32_t show_quartgrid = 0, hide_grid = 0;
68
69 tiledata *newundotilebuf;
70 std::vector<newcombo> undocombobuf;
71
72 BITMAP *selection_pattern;
73 byte selection_grid[18][18];
74 byte selection_anchor=0;
75
76 enum {selection_mode_normal, selection_mode_add, selection_mode_subtract, selection_mode_exclude};
77 BITMAP *selecting_pattern;
78 int32_t selecting_x1, selecting_x2, selecting_y1, selecting_y2;
79
80 extern int32_t bidcomboscripts_cnt;
81 extern script_struct bidcomboscripts[NUMSCRIPTSCOMBODATA];
82
83 BITMAP *intersection_pattern;
84
85 byte relational_template[48][4]=
86 {
87 { 0, 0, 0, 0 },
88 { 0, 1, 0, 0 },
89 { 1, 0, 0, 0 },
90 { 1, 1, 0, 0 },
91 { 0, 0, 1, 0 },
92 { 0, 1, 1, 0 },
93 { 1, 0, 1, 0 },
94 { 1, 1, 1, 0 },
95 { 0, 0, 0, 1 },
96 { 0, 1, 0, 1 },
97 { 1, 0, 0, 1 },
98 { 1, 1, 0, 1 },
99 { 0, 0, 1, 1 },
100 { 0, 1, 1, 1 },
101 { 1, 0, 1, 1 },
102 { 1, 1, 1, 1 },
103 { 0, 2, 0, 2 },
104 { 1, 2, 0, 2 },
105 { 0, 2, 1, 2 },
106 { 1, 2, 1, 2 },
107 { 3, 3, 0, 0 },
108 { 3, 3, 1, 0 },
109 { 3, 3, 0, 1 },
110 { 3, 3, 1, 1 },
111 { 3, 4, 0, 2 },
112 { 3, 4, 1, 2 },
113 { 2, 0, 2, 0 },
114 { 2, 1, 2, 0 },
115 { 2, 0, 2, 1 },
116 { 2, 1, 2, 1 },
117 { 2, 2, 2, 2 },
118 { 4, 3, 2, 0 },
119 { 4, 3, 2, 1 },
120 { 4, 4, 2, 2 },
121 { 0, 0, 3, 3 },
122 { 0, 1, 3, 3 },
123 { 1, 0, 3, 3 },
124 { 1, 1, 3, 3 },
125 { 0, 2, 3, 4 },
126 { 1, 2, 3, 4 },
127 { 3, 3, 3, 3 },
128 { 3, 4, 3, 4 },
129 { 2, 0, 4, 3 },
130 { 2, 1, 4, 3 },
131 { 2, 2, 4, 4 },
132 { 4, 3, 4, 3 },
133 { 4, 4, 4, 4 },
134 { 5, 5, 5, 5 }
135 };
136
137 byte dungeon_carving_template[96][4]=
138 {
139 { 0, 0, 0, 0 },
140 { 0, 1, 0, 0 },
141 { 1, 0, 0, 0 },
142 { 1, 1, 0, 0 },
143 { 0, 0, 1, 0 },
144 { 0, 1, 1, 0 },
145 { 1, 0, 1, 0 },
146 { 1, 1, 1, 0 },
147 { 0, 0, 0, 1 },
148 { 0, 1, 0, 1 },
149 { 1, 0, 0, 1 },
150 { 1, 1, 0, 1 },
151 { 0, 0, 1, 1 },
152 { 0, 1, 1, 1 },
153 { 1, 0, 1, 1 },
154 { 1, 1, 1, 1 },
155 { 0, 2, 0, 2 },
156 { 1, 2, 0, 2 },
157 { 0, 2, 1, 2 },
158 { 1, 2, 1, 2 },
159 { 3, 3, 0, 0 },
160 { 3, 3, 1, 0 },
161 { 3, 3, 0, 1 },
162 { 3, 3, 1, 1 },
163 { 3, 4, 0, 2 },
164 { 3, 4, 1, 2 },
165 { 2, 0, 2, 0 },
166 { 2, 1, 2, 0 },
167 { 2, 0, 2, 1 },
168 { 2, 1, 2, 1 },
169 { 2, 2, 2, 2 },
170 { 4, 3, 2, 0 },
171 { 4, 3, 2, 1 },
172 { 4, 4, 2, 2 },
173 { 0, 0, 3, 3 },
174 { 0, 1, 3, 3 },
175 { 1, 0, 3, 3 },
176 { 1, 1, 3, 3 },
177 { 0, 2, 3, 4 },
178 { 1, 2, 3, 4 },
179 { 3, 3, 3, 3 },
180 { 3, 4, 3, 4 },
181 { 2, 0, 4, 3 },
182 { 2, 1, 4, 3 },
183 { 2, 2, 4, 4 },
184 { 4, 3, 4, 3 },
185 { 4, 4, 4, 4 },
186 { 5, 5, 5, 5 },
187
188 { 5, 5, 5, 5 },
189 { 6, 6, 6, 6 },
190 { 7, 7, 7, 7 },
191 { 7, 6, 7, 6 },
192 { 8, 8, 8, 8 },
193 { 16, 6, 8, 15 },
194 { 7, 7, 8, 8 },
195 { 7, 6, 8, 15 },
196 { 9, 9, 9, 9 },
197 { 6, 6, 9, 9 },
198 { 7, 17, 14, 9 },
199 { 7, 6, 14, 9 },
200 { 8, 9, 8, 9 },
201 { 16, 6, 8, 9 },
202 { 7, 17, 8, 9 },
203 { 7, 6, 8, 9 },
204 { 10, 10, 10, 10 },
205 { 7, 10, 14, 10 },
206 { 16, 10, 8, 10 },
207 { 7, 10, 8, 10 },
208 { 11, 11, 11, 11 },
209 { 11, 11, 8, 15 },
210 { 11, 11, 14, 9 },
211 { 11, 11, 8, 9 },
212 { 14, 14, 14, 14 },
213 { 14, 14, 8, 14 },
214 { 12, 12, 12, 12 },
215 { 12, 6, 12, 15 },
216 { 12, 17, 12, 9 },
217 { 12, 6, 12, 9 },
218 { 12, 10, 12, 10 },
219 { 15, 15, 15, 15 },
220 { 15, 15, 15, 9 },
221 { 15, 14, 12, 10 },
222 { 13, 13, 13, 13 },
223 { 16, 6, 13, 13 },
224 { 7, 17, 13, 13 },
225 { 7, 6, 13, 13 },
226 { 16, 16, 16, 16 },
227 { 7, 16, 16, 16 },
228 { 11, 11, 13, 13 },
229 { 11, 14, 13, 16 },
230 { 17, 17, 17, 17 },
231 { 17, 6, 17, 17 },
232 { 12, 10, 17, 16 },
233 { 15, 11, 17, 13 },
234 { 15, 14, 17, 16 },
235 { 18, 18, 18, 18 }
236 };
237
238 struct tile_move_data
239 {
240 int32_t copies;
241 int32_t dest_first;
242 int32_t dest_last;
243 int32_t src_first;
244 int32_t src_last;
245 int32_t dest_top;
246 int32_t dest_bottom;
247 int32_t src_top;
248 int32_t src_bottom;
249 int32_t src_left, src_right;
250 int32_t src_width, src_height;
251 int32_t dest_left, dest_right;
252 int32_t dest_width, dest_height;
253 int32_t rows, cols;
254 bool rect, move;
255
256 tile_move_data()
257 {
258 copies = dest_first = dest_last = src_first = src_last = dest_top =
259 dest_bottom = src_top = src_bottom = src_left = src_right =
260 src_width = src_height = dest_left = dest_right = dest_width =
261 dest_height = rows = cols = 0;
262 rect = move = false;
263 }
264
265 tile_move_data(tile_move_data const& other)
266 {
267 copy(other);
268 }
269
270 tile_move_data& operator=(tile_move_data const& other)
271 {
272 copy(other);
273 return *this;
274 }
275
276 void copy(tile_move_data const& other)
277 {
278 copies = other.copies;
279 dest_first = other.dest_first;
280 dest_last = other.dest_last;
281 src_first = other.src_first;
282 src_last = other.src_last;
283 dest_top = other.dest_top;
284 dest_bottom = other.dest_bottom;
285 src_top = other.src_top;
286 src_bottom = other.src_bottom;
287 src_left = other.src_left;
288 src_right = other.src_right;
289 src_width = other.src_width;
290 src_height = other.src_height;
291 dest_left = other.dest_left;
292 dest_right = other.dest_right;
293 dest_width = other.dest_width;
294 dest_height = other.dest_height;
295 rows = other.rows;
296 cols = other.cols;
297 rect = other.rect;
298 move = other.move;
299 }
300
301 void flip()
302 {
303 zc_swap(src_first, dest_first);
304 zc_swap(src_last, dest_last);
305 zc_swap(src_top, dest_top);
306 zc_swap(src_bottom, dest_bottom);
307 zc_swap(src_left, dest_left);
308 zc_swap(src_right, dest_right);
309 zc_swap(src_width, dest_width);
310 zc_swap(src_height, dest_height);
311 }
312 };
313 bool do_movetile_united(tile_move_data const& tmd);
314
315 struct combo_move_data
316 {
317 int32_t tile, tile2, copy1, copycnt;
318 combo_move_data() : tile(0), tile2(0), copy1(0), copycnt(0){}
319 combo_move_data(combo_move_data const& other)
320 {
321 copy(other);
322 }
323 combo_move_data& operator=(combo_move_data const& other)
324 {
325 copy(other);
326 return *this;
327 }
328 void copy(combo_move_data const& other)
329 {
330 tile = other.tile;
331 tile2 = other.tile2;
332 copy1 = other.copy1;
333 copycnt = other.copycnt;
334 }
335
336 void flip()
337 {
338 int32_t tcnt = tile2-tile+1;
339 int32_t cpy2 = copy1+copycnt-1;
340 zc_swap(tile,copy1);
341 tile2 = cpy2;
342 copycnt = tcnt;
343 }
344 };
345
346 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing = false);
347 static optional<ComboMoveUndo> last_combo_move_list;
348 static optional<TileMoveUndo> last_tile_move_list;
349
350 int refl_flags = 0;
351 enum
352 {
353 REFL_90CW, REFL_HFLIP,
354 REFL_90CCW, REFL_VFLIP,
355 REFL_180, REFL_DBLFLIP,
356 REFL_MAX
357 };
358 const char *reflbtn_names[] =
359 {
360 "90 CW", "HFlip",
361 "90 CCW", "VFlip",
362 "180 Rot", "Diag Flip"
363 };
364 int bgmode = 0, xmode = 0;
365 const char *bgmodebtn_names[] =
366 {
367 "BG Color 0", "BG Trans."
368 };
369 const char *xmodebtn_names[] =
370 {
371 "X", "No X"
372 };
373 enum
374 {
375 XMODE_X, XMODE_NOX,
376 XMODE_MAX
377 };
378 enum
379 {
380 BGMODE_0, BGMODE_TRANSP,
381 BGMODE_MAX
382 };
383
384 void merge_tiles(int32_t dest_tile, int32_t src_quarter1, int32_t src_quarter2, int32_t src_quarter3, int32_t src_quarter4)
385 {
386 int32_t size=tilesize(newtilebuf[dest_tile].format)>>4;
387 int32_t size2=size>>1;
388
389 if(newtilebuf[dest_tile].data==NULL)
390 {
391 reset_tile(newtilebuf, dest_tile, newtilebuf[src_quarter1>>2].format);
392 }
393
394 int32_t i=0;
395
396 if((dest_tile<<2)+i!=src_quarter1)
397 {
398 for(int32_t j=0; j<8; ++j)
399 {
400 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter1>>2].data[((j+((src_quarter1&2)<<2))*size)+((src_quarter1&1)*size2)]), size2);
401 }
402 }
403
404 i=1;
405
406 if((dest_tile<<2)+i!=src_quarter2)
407 {
408 for(int32_t j=0; j<8; ++j)
409 {
410 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter2>>2].data[((j+((src_quarter2&2)<<2))*size)+((src_quarter2&1)*size2)]), size2);
411 }
412 }
413
414 i=2;
415
416 if((dest_tile<<2)+i!=src_quarter3)
417 {
418 for(int32_t j=0; j<8; ++j)
419 {
420 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter3>>2].data[((j+((src_quarter3&2)<<2))*size)+((src_quarter3&1)*size2)]), size2);
421 }
422 }
423
424 i=3;
425
426 if((dest_tile<<2)+i!=src_quarter4)
427 {
428 for(int32_t j=0; j<8; ++j)
429 {
430 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter4>>2].data[((j+((src_quarter4&2)<<2))*size)+((src_quarter4&1)*size2)]), size2);
431 }
432 }
433 }
434
435 static void make_combos(int32_t startTile, int32_t endTile, int32_t cs)
436 {
437 al_trace("inside make_combos()\n");
438 int32_t startCombo=0;
439
440 if(!select_combo_2(startCombo,cs))
441 return;
442
443 int32_t temp=combobuf[startCombo].o_tile;
444 combobuf[startCombo].set_tile(startTile);
445
446 if(!edit_combo(startCombo, false, cs))
447 {
448 combobuf[startCombo].set_tile(temp);
449 return;
450 }
451
452 go_combos();
453
454 for(int32_t i=0; i<=endTile-startTile; i++)
455 {
456 combobuf[startCombo+i]=combobuf[startCombo];
457 combobuf[startCombo+i].set_tile(startTile+i);
458 }
459
460 setup_combo_animations();
461 setup_combo_animations2();
462 }
463
464 static void make_combos_rect(int32_t top, int32_t left, int32_t numRows, int32_t numCols, int32_t cs)
465 {
466 int32_t startCombo=0;
467
468 if(!select_combo_2(startCombo, cs))
469 return;
470
471 int32_t startTile=top*TILES_PER_ROW+left;
472 int32_t temp=combobuf[startCombo].o_tile;
473 combobuf[startCombo].set_tile(startTile);
474
475 if(!edit_combo(startCombo, false, cs))
476 {
477 al_trace("make_combos_rect() early return\n");
478 combobuf[startCombo].set_tile(temp);
479 return;
480 }
481
482 bool smartWrap=false;
483 if(numCols!=4 && numRows>1)
484 {
485 char buf[64];
486 if(numCols<4)
487 sprintf(buf, "Limit to %d column%s?", numCols, numCols==1 ? "" : "s");
488 else
489 sprintf(buf, "Fit to 4 columns?"); // Meh, whatever.
490 int32_t ret=jwin_alert("Wrapping", buf, NULL, NULL, "&Yes", "&No", 'y', 'n', get_zc_font(font_lfont));
491 if(ret==1)
492 smartWrap=true;
493 }
494
495 go_combos();
496
497 int32_t combo=startCombo-1;
498 for(int32_t row=0; row<numRows; row++)
499 {
500 for(int32_t col=0; col<numCols; col++)
501 {
502 int32_t tile=startTile+row*TILES_PER_ROW+col;
503 if(smartWrap)
504 // Add 4 per row, and another numRows*4 for every 4 columns
505 // (col&0xFC==col/4*4), and then the column %4
506 combo=startCombo+4*row+(col&0xFC)*numRows+col%4;
507 else
508 combo++;
509
510 combobuf[combo]=combobuf[startCombo];
511 combobuf[combo].set_tile(tile);
512 }
513 }
514
515 setup_combo_animations();
516 setup_combo_animations2();
517 }
518
519 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t c);
520
521 static bool nogotiles = false;
522 static bool nogocombos = false;
523
524 void go_tiles()
525 {
526 if(nogotiles) return;
527 last_tile_move_list = nullopt;
528 for(int32_t i=0; i<NEWMAXTILES; ++i)
529 {
530 newundotilebuf[i].format=newtilebuf[i].format;
531
532 if(newundotilebuf[i].data!=NULL)
533 {
534 free(newundotilebuf[i].data);
535 }
536
537 newundotilebuf[i].data=(byte *)malloc(tilesize(newundotilebuf[i].format));
538
539 if(newundotilebuf[i].data==NULL)
540 {
541 Z_error_fatal("Unable to initialize undo tile #%ld.\n", i);
542 }
543
544 memcpy(newundotilebuf[i].data,newtilebuf[i].data,tilesize(newundotilebuf[i].format));
545 }
546 }
547
548 void go_slide_tiles(int32_t columns, int32_t rows, int32_t top, int32_t left)
549 {
550 for(int32_t c=0; c<columns; c++)
551 {
552 for(int32_t r=0; r<rows; r++)
553 {
554 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
555 newundotilebuf[t].format=newtilebuf[t].format;
556
557 if(newundotilebuf[t].data!=NULL)
558 {
559 free(newundotilebuf[t].data);
560 }
561
562 newundotilebuf[t].data=(byte *)malloc(tilesize(newundotilebuf[t].format));
563
564 if(newundotilebuf[t].data==NULL)
565 {
566 Z_error_fatal("Unable to initialize undo tile #%ld.\n", t);
567 }
568
569 memcpy(newundotilebuf[t].data,newtilebuf[t].data,tilesize(newundotilebuf[t].format));
570 }
571 }
572 }
573
574 void comeback_tiles()
575 {
576 if(last_tile_move_list)
577 {
578 last_tile_move_list->undo();
579 last_tile_move_list = nullopt;
580 }
581 for(dword i=0; i<NEWMAXTILES; ++i)
582 {
583 if(newtilebuf[i].format != newundotilebuf[i].format || !newtilebuf[i].data)
584 {
585 newtilebuf[i].format = newundotilebuf[i].format;
586
587 if(newtilebuf[i].data!=NULL)
588 free(newtilebuf[i].data);
589 newtilebuf[i].data=(byte *)malloc(tilesize(newtilebuf[i].format));
590 if(newtilebuf[i].data==NULL)
591 Z_error_fatal("Unable to initialize tile #%ld.\n", i);
592 }
593
594 memcpy(newtilebuf[i].data,newundotilebuf[i].data,tilesize(newtilebuf[i].format));
595 }
596
597 register_blank_tiles();
598 register_used_tiles();
599 }
600
601 void go_combos()
602 {
603 if(nogocombos) return;
604 last_combo_move_list = nullopt;
605
606 undocombobuf = combobuf;
607 }
608
609 void comeback_combos()
610 {
611 if(last_combo_move_list)
612 {
613 last_combo_move_list->undo();
614 last_combo_move_list = nullopt;
615 }
616
617 combobuf = undocombobuf;
618 }
619
620 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t s)
621 {
622 line(dest,x,y,x+s,y+s,c);
623 line(dest,x+s,y,x,y+s,c);
624 }
625 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t w, int32_t h)
626 {
627 line(dest,x,y,x+w,y+h,c);
628 line(dest,x+w,y,x,y+h,c);
629 }
630
631 enum {gm_light, gm_dark, gm_max};
632 int32_t gridmode=gm_light;
633
634 bool has_selection()
635 {
636 for(int32_t i=1; i<17; ++i)
637 {
638 for(int32_t j=1; j<17; ++j)
639 {
640 if(selection_grid[i][j])
641 {
642 return true;
643 }
644 }
645 }
646
647 return false;
648 }
649
650 void draw_selection_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
651 {
652 drawing_mode(DRAW_MODE_COPY_PATTERN, selection_pattern, selection_anchor>>3, 0);
653
654 for(int32_t i=1; i<18; ++i)
655 {
656 for(int32_t j=1; j<18; ++j)
657 {
658 // zoomtile16(screen2,tile,79,31,cs,flip,8);
659 if(selection_grid[i-1][j]!=selection_grid[i][j])
660 {
661 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
662 }
663
664 if(selection_grid[i][j-1]!=selection_grid[i][j])
665 {
666 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
667 }
668 }
669 }
670
671 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
672 // selection_anchor=(selection_anchor+1)%64;
673 }
674
675 bool is_selecting()
676 {
677 return (selecting_x1>-1&&selecting_x2>-1&&selecting_y1>-1&&selecting_y2>-1);
678 }
679
680 void draw_selecting_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
681 {
682 int32_t x1=zc_min(selecting_x1,selecting_x2);
683 int32_t x2=zc_max(selecting_x1,selecting_x2);
684 int32_t y1=zc_min(selecting_y1,selecting_y2);
685 int32_t y2=zc_max(selecting_y1,selecting_y2);
686
687 // rect(dest, x+(x1*scale2), y+(y1*scale2), x+((x2+1)*scale2), y+((y2+1)*scale2), 255);
688 for(int32_t i=1; i<18; ++i)
689 {
690 for(int32_t j=1; j<18; ++j)
691 {
692 drawing_mode(DRAW_MODE_COPY_PATTERN, selecting_pattern, selection_anchor>>3, 0);
693
694 if(((j>=y1+1)&&(j<=y2+1))&&((i==x1+1)||(i==x2+2)))
695 {
696 if(selection_grid[i-1][j]!=selection_grid[i][j])
697 {
698 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
699 }
700
701 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
702 }
703
704 if(((i>=x1+1)&&(i<=x2+1))&&((j==y1+1)||(j==y2+2)))
705 {
706 if(selection_grid[i][j-1]!=selection_grid[i][j])
707 {
708 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
709 }
710
711 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
712 }
713 }
714 }
715
716 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
717 // selection_anchor=(selection_anchor+1)%64;
718 }
719
720 void unfloat_selection();
721 bool floating_sel = false;
722 byte floatsel[256];
723 byte undofloatsel[256];
724 bool undo_is_floatsel = false;
725
726
727 void add_color_to_selection(int32_t color)
728 {
729 unfloat_selection();
730 for(int32_t i=1; i<17; ++i)
731 {
732 for(int32_t j=1; j<17; ++j)
733 {
734 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
735 {
736 selection_grid[i][j]=1;
737 }
738 }
739 }
740 }
741
742 void remove_color_from_selection(int32_t color)
743 {
744 unfloat_selection();
745 for(int32_t i=1; i<17; ++i)
746 {
747 for(int32_t j=1; j<17; ++j)
748 {
749 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
750 {
751 selection_grid[i][j]=0;
752 }
753 }
754 }
755 }
756
757 void intersect_color_with_selection(int32_t color)
758 {
759 unfloat_selection();
760 for(int32_t i=1; i<17; ++i)
761 {
762 for(int32_t j=1; j<17; ++j)
763 {
764 if((unpackbuf[((j-1)<<4)+(i-1)]==color)&&(selection_grid[i][j]==1))
765 {
766 selection_grid[i][j]=1;
767 }
768 else
769 {
770 selection_grid[i][j]=0;
771 }
772 }
773 }
774 }
775
776 bool is_in_selection(int32_t x, int32_t y)
777 {
778 x %= 16; y %= 16;
779 if(x < 0) x = (16 - abs(x));
780 if(y < 0) y = (16 - abs(y));
781 return (!has_selection()||(selection_grid[x+1][y+1]!=0));
782 }
783
784 void zoomtile16(BITMAP *dest,int32_t tile,int32_t x,int32_t y,int32_t cset,int32_t flip,int32_t m)
785 {
786 // rectfill(dest,x,y,x+(16*m),y+(16*m),gridmode==gm_light?jwin_pal[jcMEDLT]:jwin_pal[jcDARK]);
787 int gridcol = gridmode==gm_light?vc(7):vc(8);
788
789 cset <<= 4;
790 if(newtilebuf[tile].format>tf4Bit)
791 cset=0;
792
793 int g = hide_grid ? 1 : 0;
794 byte transp_col = (bgmode == BGMODE_TRANSP ? jwin_pal[jcBOX] : 0+cset);
795 rectfill(dest,x,y,x+(16*m)+g,y+(16*m)+g,transp_col);
796
797 unpack_tile(newtilebuf, tile, 0, false);
798 byte *si = unpackbuf;
799 for(int32_t cy=0; cy<16; cy++)
800 {
801 for(int32_t cx=0; cx<16; cx++)
802 {
803 byte col = (floating_sel && floatsel[cx+(cy<<4)]) ? floatsel[cx+(cy<<4)] : *si;
804 int32_t dx = ((flip&1)?15-cx:cx)*m;
805 int32_t dy = ((flip&2)?15-cy:cy)*m;
806 if(col)
807 rectfill(dest,x+dx,y+dy,x+dx+m-1,y+dy+m-1,col+cset);
808
809 if(!col && xmode == XMODE_X)
810 little_x(dest,x+dx+m/4,y+dy+m/4,invcol,m/2);
811
812 ++si;
813 }
814 }
815
816 if(!hide_grid)
817 {
818 for(int cx = 0; cx <= 16; ++cx)
819 vline(dest,x+(cx*m),y,y+(16*m)-1,gridcol);
820 for(int cy = 0; cy <= 16; ++cy)
821 hline(dest,x,y+(cy*m),x+(16*m)-1,gridcol);
822 }
823
824 if(show_quartgrid)
825 {
826 int offs = (8*m);
827 const int RAD = 3;
828 rectfill(dest,x+offs-RAD,y,x+offs+RAD,y+(16*m),gridcol);
829 rectfill(dest,x,y+offs-RAD,x+(16*m),y+offs+RAD,gridcol);
830 }
831
832 if(has_selection()||is_selecting())
833 {
834 selection_anchor=(selection_anchor+1)%64;
835
836 if(has_selection()||is_selecting())
837 draw_selection_outline(dest, x, y, m);
838
839 if(is_selecting())
840 draw_selecting_outline(dest, x, y, m);
841 }
842 }
843
844 void draw_text_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,int32_t flags,bool jwin)
845 {
846 if(!jwin)
847 {
848 if(flags&D_SELECTED)
849 {
850 zc_swap(fg,bg);
851 }
852
853 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
854 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
855 rect(dest,x,y,x+w-2,y+h-2,fg);
856 textout_centre_ex(dest,font,text,(x+x+w)>>1,((y+y+h)>>1)-4,fg,-1);
857 }
858 else
859 {
860 jwin_draw_text_button(dest, x, y, w, h, text, flags, true);
861 }
862 }
863
864 void draw_icon_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,int icon,int32_t bg,int32_t fg,int32_t flags,bool jwin)
865 {
866 if(!jwin)
867 {
868 if(flags&D_SELECTED)
869 {
870 zc_swap(fg,bg);
871 }
872
873 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
874 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
875 rect(dest,x,y,x+w-2,y+h-2,fg);
876 jwin_draw_icon(dest,x+w/2,y+h/2,fg,icon,icon_proportion(icon,w,h),true);
877 }
878 else
879 {
880 jwin_draw_icon_button(dest, x, y, w, h, icon, flags, true);
881 }
882 }
883
884 void draw_layer_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t flags)
885 {
886 if(flags&D_SELECTED)
887 {
888 rect(dest, x, y, x+w-1, y+h-1, jwin_pal[jcDARK]);
889 ++x;
890 ++y;
891 --w;
892 --h;
893 }
894 rectfill(dest,x+1,y+1,x+w-3,y+h-3,jwin_pal[(flags&D_SELECTED ? jcMEDDARK : jcBOX)]);
895 jwin_draw_frame(dest, x, y, w, h, (flags&D_SELECTED ? FR_DARK : FR_BOX));
896
897 //Forcibly fit the text within the button
898 char buf[512] = {0};
899 strcpy(buf, text);
900
901 bool dis = (flags&D_DISABLED);
902 auto hei = text_height(font);
903 auto len = text_length(font,buf);
904 auto borderwid = 8;
905 if(len > w - borderwid + (dis ? 1 : 0))
906 {
907 auto ind = strlen(buf) - 1;
908 auto dotcount = 0;
909 while(len > w - borderwid + (dis ? 1 : 0))
910 {
911 if(dotcount >= 2)
912 buf[ind+2] = 0;
913 else ++dotcount;
914 buf[ind--] = '.';
915 len = text_length(font,buf);
916 }
917 }
918 if(dis)
919 {
920 ++len; ++hei;
921 }
922 BITMAP* tmp = create_bitmap_ex(8,len,hei);
923 clear_bitmap(tmp);
924 if(dis)
925 {
926 textout_ex(tmp,font,buf,1,1,jwin_pal[jcLIGHT],-1);
927 textout_ex(tmp,font,buf,0,0,jwin_pal[jcDISABLED_FG],-1);
928 }
929 else
930 textout_ex(tmp,font,buf,0,0,jwin_pal[jcBOXFG],-1);
931 auto tx = x+((w-len)/2);
932 auto ty = y+((h-hei)/2);
933 if(len > w-borderwid)
934 {
935 tx = x+borderwid/2;
936 len = w-borderwid;
937 }
938 if(hei > h-borderwid)
939 {
940 ty = y+borderwid/2;
941 hei = h-borderwid;
942 }
943 masked_blit(tmp,dest, 0,0, tx,ty, len, hei);
944 destroy_bitmap(tmp);
945 }
946
947 bool do_layer_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text, int32_t flags, bool toggleflag)
948 {
949 bool over=false;
950
951 while(gui_mouse_b())
952 {
953 //vsync();
954 if(mouse_in_rect(x,y,w,h))
955 {
956 if(!over)
957 {
958 vsync();
959 draw_layer_button(screen, x, y, w, h, text, flags^D_SELECTED);
960 over=true;
961
962 update_hw_screen();
963 }
964 }
965 else
966 {
967 if(over)
968 {
969 vsync();
970 draw_layer_button(screen, x, y, w, h, text, flags);
971 over=false;
972
973 update_hw_screen();
974 }
975 }
976 rest(1);
977 }
978
979 if(over)
980 {
981 vsync();
982 draw_layer_button(screen, x, y, w, h, text, toggleflag ? flags^D_SELECTED : flags);
983
984 update_hw_screen();
985 }
986
987 return over;
988 }
989
990 bool do_text_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,bool jwin, bool sel)
991 {
992 bool over=false;
993
994 while(gui_mouse_b())
995 {
996 custom_vsync();
997
998 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
999 {
1000 if(!over)
1001 {
1002 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1003 over=true;
1004 }
1005 }
1006 else
1007 {
1008 if(over)
1009 {
1010 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?D_SELECTED:0,jwin);
1011 over=false;
1012 }
1013 }
1014 }
1015
1016 if(over)
1017 {
1018 custom_vsync();
1019 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1020 }
1021
1022 return over;
1023 }
1024
1025 void draw_graphics_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,int32_t flags,bool jwin,bool overlay)
1026 {
1027 if(!jwin)
1028 {
1029 if(flags&D_SELECTED)
1030 {
1031 zc_swap(fg,bg);
1032 }
1033
1034 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
1035 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
1036 rect(dest,x,y,x+w-2,y+h-2,fg);
1037 int32_t g = (flags & D_SELECTED) ? 1 : 0;
1038
1039 if(overlay)
1040 {
1041 masked_blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1042 }
1043 else
1044 {
1045 blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1046 }
1047 }
1048 else
1049 {
1050 jwin_draw_graphics_button(dest, x, y, w, h, bmp, bmp2, flags, false, overlay);
1051 }
1052 }
1053
1054 bool do_graphics_button(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1055 {
1056 bool over=false;
1057
1058 while(gui_mouse_b())
1059 {
1060 custom_vsync();
1061
1062 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1063 {
1064 if(!over)
1065 {
1066 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1067 over=true;
1068 }
1069 }
1070 else
1071 {
1072 if(over)
1073 {
1074 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1075 over=false;
1076 }
1077 }
1078 }
1079
1080 return over;
1081 }
1082
1083 bool do_graphics_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1084 {
1085 bool over=false;
1086
1087 while(gui_mouse_b())
1088 {
1089 custom_vsync();
1090
1091 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1092 {
1093 if(!over)
1094 {
1095 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1096 over=true;
1097 }
1098 }
1099 else
1100 {
1101 if(over)
1102 {
1103 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1104 over=false;
1105 }
1106 }
1107 }
1108
1109 if(over)
1110 {
1111 custom_vsync();
1112 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1113 }
1114
1115 return over;
1116 }
1117 // circle(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1118 // circlefill(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1119
1120 void draw_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg, int32_t value)
1121 {
1122 //these are here to bypass compiler warnings about unused arguments
1123 bg=bg;
1124 fg=fg;
1125
1126 int32_t r, center;
1127
1128 for(int32_t k=0; k<7; k++)
1129 {
1130 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1131 {
1132 // circle(dest, x+(k*25)+4, y+4, 4, fg);
1133 // circlefill(dest, x+(k*25)+4, y+4, 2, (value==k)?fg:bg);
1134 //*
1135 r = 9/2;
1136
1137 center = x+(k*25)+r;
1138 rectfill(dest, x+(k*25), y, x+(k*25)+9-1, y+9-1, jwin_pal[jcBOX]);
1139
1140 circlefill(dest, center, y+r, r, jwin_pal[jcLIGHT]);
1141 arc(dest, center, y+r, itofix(32), itofix(160), r, jwin_pal[jcMEDDARK]);
1142 circlefill(dest, center, y+r, r-1, jwin_pal[jcMEDLT]);
1143 arc(dest, center, y+r, itofix(32), itofix(160), r-1, jwin_pal[jcDARK]);
1144 circlefill(dest, center, y+r, r-2, jwin_pal[jcLIGHT]);
1145
1146 if(value==k)
1147 {
1148 circlefill(dest, center, y+r, r-3, jwin_pal[jcDARK]);
1149 }
1150
1151 //*/
1152 }
1153 }
1154 }
1155
1156 void do_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg,int32_t &value)
1157 {
1158 while(gui_mouse_b())
1159 {
1160 custom_vsync();
1161
1162 for(int32_t k=0; k<7; k++)
1163 {
1164 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1165 {
1166 //if on radio button
1167 if(isinRect(gui_mouse_x(),gui_mouse_y(),x+(k*25),y,x+(k*25)+8,y+8))
1168 {
1169 value=k;
1170 draw_layerradio(dest,x,y,bg,fg,value);
1171 refresh(rMENU);
1172 }
1173 }
1174 }
1175 }
1176 }
1177
1178 //*************** tile flood fill stuff **************
1179
1180 byte tf_c;
1181 byte tf_u;
1182
1183 void tile_floodfill_rec(int32_t x,int32_t y)
1184 {
1185 if(is_in_selection(x,y))
1186 {
1187 while(x>0 && (unpackbuf[(y<<4)+x-1] == tf_u))
1188 --x;
1189
1190 while(x<=15 && (unpackbuf[(y<<4)+x] == tf_u))
1191 {
1192 if(is_in_selection(x,y))
1193 {
1194 unpackbuf[(y<<4)+x] = tf_c;
1195 }
1196
1197 if(y>0 && (unpackbuf[((y-1)<<4)+x] == tf_u))
1198 tile_floodfill_rec(x,y-1);
1199
1200 if(y<15 && (unpackbuf[((y+1)<<4)+x] == tf_u))
1201 tile_floodfill_rec(x,y+1);
1202
1203 ++x;
1204 }
1205 }
1206 }
1207
1208 void tile_floodfill(int32_t tile,int32_t x,int32_t y,byte c)
1209 {
1210 if(is_in_selection(x,y))
1211 {
1212 if(floating_sel)
1213 {
1214 memcpy(unpackbuf, floatsel, 256);
1215 }
1216 else unpack_tile(newtilebuf, tile, 0, false);
1217 tf_c = c;
1218 tf_u = unpackbuf[(y<<4)+x];
1219
1220 if(tf_u != tf_c)
1221 tile_floodfill_rec(x,y);
1222 if(floating_sel)
1223 {
1224 memcpy(floatsel, unpackbuf, 256);
1225 }
1226 else pack_tile(newtilebuf,unpackbuf,tile);
1227 }
1228 }
1229
1230 //***************** tile editor stuff *****************
1231 9 size_and_pos ok_button(302,562,71,21);
1232 9 size_and_pos cancel_button(376,562,71,21);
1233 9 size_and_pos edit_button(550,562,86,21);
1234 9 size_and_pos hlcbox(742,392,16,16);
1235 9 size_and_pos hov_prev(742,338,50,50);
1236 9 size_and_pos cpalette_4(648,416,4,4,64,64);
1237 9 size_and_pos cpalette_8(648,416,16,14,16,18);
1238 9 size_and_pos fg_prev(648,316,50,50);
1239 9 size_and_pos bg_prev(648+30,316+30,50,50);
1240 9 size_and_pos zoomtile(124,32,16,16,32,32);
1241 9 size_and_pos prev_til_1(648,31,96,96);
1242 9 size_and_pos prev_til_2(752,31,96,96);
1243 9 size_and_pos prev_til_3(648,135,96,96);
1244 9 size_and_pos prev_til_4(752,135,96,96);
1245 9 size_and_pos status_info(648,308-(4*8),1,4,1,8);
1246 9 size_and_pos hover_info(742,338-(3*8),1,3,1,8);
1247 9 size_and_pos color_info(4,189,1,1,116,8);
1248 9 size_and_pos color_info_btn(24,189,96,21);
1249 9 size_and_pos tool_btns(22,29,2,4,39,39);
1250 9 size_and_pos x_btn(890,5,15,13);
1251 9 size_and_pos info_btn(872,5,15,13);
1252 9 size_and_pos hidegrid_cbox(124,552,16,16);
1253 9 size_and_pos quartgrid_cbox(124,572,16,16);
1254 9 size_and_pos reflbtn_grid(124,610,2,3,71,21);
1255 9 size_and_pos xmodebtn_grid(300,610,1,2,90,21);
1256 9 size_and_pos bgmodebtn_grid(390,610,1,2,90,21);
1257
1258 int32_t c1=1;
1259 int32_t c2=0;
1260 int32_t floating_tile = -1;
1261 int32_t tool = t_pen;
1262 int32_t old_tool = -1;
1263 int32_t tool_cur = -1;
1264 int32_t select_mode = 0;
1265 int32_t drawing=0;
1266
1267 bool qgrid_tool(int tool)
1268 {
1269 switch(tool)
1270 {
1271 case t_pen:
1272 case t_fill:
1273 case t_recolor:
1274 case t_wand:
1275 return true;
1276 }
1277 return false;
1278 }
1279
1280 void set_tool_sprite(int tool, int type)
1281 {
1282 int spr = ZQM_NORMAL;
1283 switch(tool)
1284 {
1285 case t_pen: spr = ZQM_SWORD; break;
1286 case t_fill: spr = ZQM_POTION; break;
1287 case t_recolor: spr = ZQM_WAND; break;
1288 case t_eyedropper: spr = ZQM_LENS; break;
1289 case t_move: spr = ZQM_GLOVE_OPEN+type; break;
1290 case t_select: spr = ZQM_HOOK_PLAIN+type; break;
1291 case t_wand: spr = ZQM_SEL_WAND_PLAIN+type; break;
1292 }
1293 MouseSprite::set(spr);
1294 }
1295 void update_tool_cursor()
1296 {
1297 int32_t temp_mouse_x=gui_mouse_x();
1298 int32_t temp_mouse_y=gui_mouse_y();
1299
1300 int32_t type=0;
1301
1302 if(has_selection())
1303 {
1304 switch(tool)
1305 {
1306 case t_select:
1307 case t_wand:
1308 type+=select_mode;
1309 break;
1310 }
1311 }
1312
1313 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
1314 {
1315 if(tool_cur==-1)
1316 set_tool_sprite(tool,type);
1317
1318 tool_cur=tool;
1319 }
1320 else if(tool_cur != -1)
1321 {
1322 MouseSprite::set(ZQM_NORMAL);
1323 tool_cur = -1;
1324 }
1325 }
1326
1327 void draw_edit_scr(int32_t tile,int32_t flip,int32_t cs,byte *oldtile, bool create_tbar)
1328 {
1329 PALETTE tpal;
1330 static BITMAP *tbar = create_bitmap_ex(8,zq_screen_w-6, 18);
1331 static BITMAP *preview_bmp = create_bitmap_ex(8, 64, 64);
1332 jwin_draw_win(screen2, 0, 0, zq_screen_w, zq_screen_h, FR_WIN);
1333
1334 if(!create_tbar)
1335 {
1336 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1337 }
1338 else
1339 {
1340 jwin_draw_titlebar(tbar, 0, 0, zq_screen_w-6, 18, "", true, true);
1341 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1342 }
1343
1344 textprintf_ex(screen2,get_zc_font(font_lfont),5,5,jwin_pal[jcTITLEFG],-1,"Tile Editor (%d)",tile);
1345
1346 clear_to_color(preview_bmp, 0);
1347
1348 zc_swap(oldtile,newtilebuf[tile].data); //Put oldtile in the tile buffer
1349 jwin_draw_win(screen2, prev_til_1.x-2,prev_til_1.y-2, prev_til_1.w+4, prev_til_1.h+4, FR_DEEP);
1350 puttile16(preview_bmp,tile,0,0,cs,flip);
1351 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_1.x, prev_til_1.y, prev_til_1.w, prev_til_1.h);
1352
1353 clear_to_color(preview_bmp, 0);
1354 jwin_draw_win(screen2, prev_til_2.x-2,prev_til_2.y-2, prev_til_2.w+4, prev_til_2.h+4, FR_DEEP);
1355 overtile16(preview_bmp,tile,0,0,cs,flip);
1356 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_2.x, prev_til_2.y, prev_til_2.w, prev_til_2.h);
1357 zc_swap(oldtile,newtilebuf[tile].data); //Swap the real tile back to the buffer
1358
1359 unpack_tile(newtilebuf, tile, 0, true);
1360 if(floating_sel)
1361 for(auto q = 0; q < 256; ++q)
1362 if(floatsel[q])
1363 unpackbuf[q] = floatsel[q];
1364 byte tmptile[256];
1365 byte *tmpptr = tmptile;
1366 zc_swap(tmpptr,newtilebuf[tile].data); //Put temp data in the tile buffer
1367 pack_tile(newtilebuf,unpackbuf,tile);
1368 clear_to_color(preview_bmp, 0);
1369
1370 jwin_draw_win(screen2, prev_til_3.x-2,prev_til_3.y-2, prev_til_3.w+4, prev_til_3.h+4, FR_DEEP);
1371 puttile16(preview_bmp,tile,0,0,cs,flip);
1372 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_3.x, prev_til_3.y, prev_til_3.w, prev_til_3.h);
1373
1374 clear_to_color(preview_bmp, 0);
1375 jwin_draw_win(screen2, prev_til_4.x-2,prev_til_4.y-2, prev_til_4.w+4, prev_til_4.h+4, FR_DEEP);
1376 overtile16(preview_bmp,tile,0,0,cs,flip);
1377 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_4.x, prev_til_4.y, prev_til_4.w, prev_til_4.h);
1378
1379 //Color info
1380 {
1381 auto fh = color_info.yscale = text_height(font);
1382 int y = color_info.y;
1383 int rx = color_info.x+color_info.xscale;
1384 color_info.h = 1;
1385 if(showcolortip)
1386 {
1387 gui_textout_ln(screen2,font,(unsigned char*)"Colors:",
1388 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1389 auto str = get_tile_colornames(tile,cs);
1390 size_t pos = 0;
1391 char buf[512] = {0};
1392 char cbuf[16] = {0};
1393 while(pos < str.size())
1394 {
1395 y += fh;
1396 if(y+fh > zq_screen_h)
1397 break; //Out of space!
1398 auto endpos = str.find_first_of('\n',pos);
1399
1400 if(endpos == std::string::npos)
1401 {
1402 strcpy(buf,str.substr(pos).c_str());
1403 pos = str.size();
1404 }
1405 else
1406 {
1407 strcpy(buf,str.substr(pos,endpos-pos+1).c_str());
1408 pos = endpos+1;
1409 }
1410 //Ensure the name fits horizontally
1411 if(text_length(font,buf) > color_info.xscale)
1412 {
1413 size_t pos = 0;
1414 for(; buf[pos]; ++pos)
1415 {
1416 if(buf[pos] == ':')
1417 {
1418 strcpy(cbuf, buf+pos);
1419 buf[pos] = 0;
1420 break;
1421 }
1422 }
1423 size_t clen = text_length(font,cbuf);
1424 size_t dotlen = text_length(font,"..");
1425
1426 while(pos > 0 && (dotlen+clen+text_length(font,buf) > color_info.xscale))
1427 buf[--pos] = 0;
1428 while(buf[pos] == ' ')
1429 buf[pos] = 0;
1430 strcat(buf,"..");
1431 strcat(buf,cbuf);
1432 }
1433 gui_textout_ln(screen2,font,(unsigned char const*)buf,
1434 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1435 ++color_info.h;
1436 }
1437 jwin_draw_frame(screen2,color_info.x-2,color_info.y-2,(color_info.w*color_info.xscale)+4,(color_info.h*color_info.yscale)+4,FR_DEEP);
1438 }
1439 else
1440 {
1441 draw_text_button(screen2,color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,
1442 "Show Colors",vc(1),vc(14),0,true);
1443 }
1444 }
1445
1446 zc_swap(tmpptr,newtilebuf[tile].data); //Swap the real tile back to the buffer
1447
1448 jwin_draw_win(screen2, zoomtile.x-3, zoomtile.y-3, (zoomtile.w*zoomtile.xscale)+5, (zoomtile.h*zoomtile.yscale)+5, FR_DEEP);
1449 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
1450
1451 if(floating_sel)
1452 textprintf_ex(screen2,font,status_info.x,status_info.y+0,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Floating selection");
1453 textprintf_ex(screen2,font,status_info.x,status_info.y+(1*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile: %d",tile);
1454 if(newtilebuf[tile].format==tf8Bit)
1455 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"8-bit");
1456 else
1457 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cset: %d",cs);
1458
1459 PALETTE temppal;
1460
1461 //palette and mouse
1462 switch(newtilebuf[tile].format)
1463 {
1464 case tf4Bit:
1465 jwin_draw_win(screen2, cpalette_4.x-2, cpalette_4.y-2, (cpalette_4.xscale*cpalette_4.w)+4, (cpalette_4.yscale*cpalette_4.h)+4, FR_DEEP);
1466 get_palette(temppal);
1467
1468 for(int32_t i=0; i<cpalette_4.w*cpalette_4.h; i++)
1469 {
1470 size_and_pos const& s = cpalette_4.subsquare(i);
1471 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,CSET(cs)+i);
1472 }
1473
1474 little_x(screen2,cpalette_4.x+1,cpalette_4.y+1,invcol,cpalette_4.xscale-5,cpalette_4.yscale-5);
1475 break;
1476
1477 case tf8Bit:
1478 jwin_draw_win(screen2, cpalette_8.x-2, cpalette_8.y-2, (cpalette_8.xscale*cpalette_8.w)+4, (cpalette_8.yscale*cpalette_8.h)+4, FR_DEEP);
1479
1480 for(int32_t i=0; i<cpalette_8.w*cpalette_8.h; ++i)
1481 {
1482 size_and_pos const& s = cpalette_8.subsquare(i);
1483 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,i);
1484 }
1485
1486 little_x(screen2,cpalette_8.x+1,cpalette_8.y+1,invcol,cpalette_8.xscale-5,cpalette_8.yscale-5);
1487 break;
1488 }
1489
1490 rect(screen2, bg_prev.x, bg_prev.y, bg_prev.x+bg_prev.w-1, bg_prev.y+bg_prev.h-1, jwin_pal[jcTEXTFG]);
1491 rectfill(screen2, bg_prev.x+1, bg_prev.y+1, bg_prev.x+bg_prev.w-2, bg_prev.y+bg_prev.h-2, jwin_pal[jcTEXTBG]);
1492 rectfill(screen2, bg_prev.x+3, bg_prev.y+3, bg_prev.x+bg_prev.w-4, bg_prev.y+bg_prev.h-4, c2+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1493
1494 if(c2==0)
1495 {
1496 little_x(screen2, bg_prev.x+1, bg_prev.y+1, invcol, bg_prev.w-2, bg_prev.h-2);
1497 }
1498
1499 rect(screen2, fg_prev.x, fg_prev.y, fg_prev.x+fg_prev.w-1, fg_prev.y+fg_prev.h-1, jwin_pal[jcTEXTFG]);
1500 rectfill(screen2, fg_prev.x+1, fg_prev.y+1, fg_prev.x+fg_prev.w-2, fg_prev.y+fg_prev.h-2, jwin_pal[jcTEXTBG]);
1501 rectfill(screen2, fg_prev.x+3, fg_prev.y+3, fg_prev.x+fg_prev.w-4, fg_prev.y+fg_prev.h-4, c1+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1502
1503 if(c1==0)
1504 {
1505 little_x(screen2, fg_prev.x+1, fg_prev.y+1, invcol, fg_prev.w-2, fg_prev.h-2);
1506 }
1507
1508 draw_text_button(screen2,ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK",vc(1),vc(14),0,true);
1509 draw_text_button(screen2,cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel",vc(1),vc(14),0,true);
1510 draw_text_button(screen2,edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal",vc(1),vc(14),0,true);
1511 draw_checkbox(screen2,hlcbox.x, hlcbox.y, hlcbox.w, hlcbox.h, tthighlight);
1512 gui_textout_ln(screen2,font,(unsigned char*)"Highlight Hover",hlcbox.x+hlcbox.w+2,hlcbox.y+hlcbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1513
1514 draw_checkbox(screen2,quartgrid_cbox.x, quartgrid_cbox.y, quartgrid_cbox.w, quartgrid_cbox.h, show_quartgrid);
1515 gui_textout_ln(screen2,font,(unsigned char*)"Quarter Grid",quartgrid_cbox.x+quartgrid_cbox.w+2,quartgrid_cbox.y+quartgrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1516
1517 draw_checkbox(screen2,hidegrid_cbox.x, hidegrid_cbox.y, hidegrid_cbox.w, hidegrid_cbox.h, hide_grid);
1518 gui_textout_ln(screen2,font,(unsigned char*)"Hide Grid",hidegrid_cbox.x+hidegrid_cbox.w+2,hidegrid_cbox.y+hidegrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1519
1520 bool qgrd = show_quartgrid && qgrid_tool(tool);
1521 gui_textout_ln(screen2,font,(unsigned char*)"Quarter-Grid Draw Modes", reflbtn_grid.x, reflbtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],qgrd?0:D_DISABLED);
1522 for(int q = 0; q < REFL_MAX; ++q)
1523 {
1524 auto& sqr = reflbtn_grid.subsquare(q);
1525 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[q],vc(1),vc(14),qgrd ? ((refl_flags&(1<<q)) ? D_SELECTED : 0) : D_DISABLED,true);
1526 }
1527 gui_textout_ln(screen2,font,(unsigned char*)"Transparent Mode", xmodebtn_grid.x, xmodebtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1528 for(int q = 0; q < XMODE_MAX; ++q)
1529 {
1530 auto& sqr = xmodebtn_grid.subsquare(q);
1531 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[q],vc(1),vc(14),(xmode == q) ? D_SELECTED : 0,true);
1532 }
1533 for(int q = 0; q < BGMODE_MAX; ++q)
1534 {
1535 auto& sqr = bgmodebtn_grid.subsquare(q);
1536 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[q],vc(1),vc(14),(bgmode == q) ? D_SELECTED : 0,true);
1537 }
1538
1539 //tool buttons
1540 for(int32_t toolbtn = 0; toolbtn < t_max; ++toolbtn)
1541 {
1542 auto bmp = toolbtn+MOUSE_BMP_SWORD;
1543 int col = toolbtn%tool_btns.w;
1544 int row = toolbtn/tool_btns.w;
1545
1546 jwin_draw_button(screen2,tool_btns.x+(col*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale,tool==toolbtn?2:0,0);
1547 masked_stretch_blit(mouse_bmp_1x[bmp][0],screen2,0,0,16,16,tool_btns.x+(col*tool_btns.xscale)+3+(tool==toolbtn?1:0),tool_btns.y+3+(row*tool_btns.yscale)+(tool==toolbtn?1:0),tool_btns.xscale-7,tool_btns.yscale-7);
1548 }
1549
1550 //coordinates
1551 {
1552 auto mx = gui_mouse_x();
1553 auto my = gui_mouse_y();
1554 int32_t ind = zoomtile.rectind(mx,my);
1555 int32_t temp_x=ind%zoomtile.w;
1556 int32_t temp_y=ind/zoomtile.w;
1557 int color = -1;
1558
1559 bool is8b = newtilebuf[tile].format > tf4Bit;
1560 if(ind > -1)
1561 {
1562 char xbuf[16];
1563 sprintf(xbuf, "x: %d", temp_x);
1564 textprintf_ex(screen2,font,status_info.x,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%s",xbuf);
1565 textprintf_ex(screen2,font,status_info.x+text_length(font,xbuf)+8,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"y: %d",temp_y);
1566 unpack_tile(newtilebuf, tile, 0, false);
1567 byte *si = unpackbuf;
1568 si+=ind;
1569 color = *si;
1570 }
1571 else if(fg_prev.rect(mx,my))
1572 color = c1;
1573 else if(bg_prev.rect(mx,my))
1574 color = c2;
1575 else color = (is8b ? cpalette_8 : cpalette_4).rectind(mx,my);
1576 if(color > -1)
1577 {
1578 get_palette(tpal);
1579 char separator = ' ';
1580 char buf[512] = {0};
1581
1582 int realcol = color+(is8b?0:CSET(cs));
1583 bool xcolor = (is8b ? realcol == 0 : (realcol%16)==0);
1584 auto& c = tpal[realcol];
1585
1586 if(tthighlight)
1587 {
1588 size_and_pos const& mainsqr = is8b ? cpalette_8 : cpalette_4;
1589 size_and_pos const& csqr = mainsqr.subsquare(color);
1590
1591 int hlcol = getHighlightColor(tpal[realcol]);
1592 int hlthick = 4;
1593 int extraborder = is8b ? 8 : 0;
1594 int borderthick = hlthick+extraborder;
1595
1596 if(is8b)
1597 {
1598 highlight_sqr(screen2, 0xED, csqr.x, mainsqr.y, csqr.w, mainsqr.h*mainsqr.yscale, hlthick); //column
1599 highlight_sqr(screen2, 0xED, mainsqr.x, csqr.y, mainsqr.w*mainsqr.xscale, csqr.h, hlthick); //row
1600 }
1601 highlight_sqr(screen2, 0xED, csqr.x-borderthick, csqr.y-borderthick, csqr.w+borderthick*2, csqr.h+borderthick*2, hlthick); //square hl
1602 rectfill(screen2, csqr.x-extraborder, csqr.y-extraborder, csqr.x+csqr.w-1+extraborder, csqr.y+csqr.h-1+extraborder, realcol); //square color
1603 if(xcolor)
1604 little_x(screen2, csqr.x-extraborder+4, csqr.y-extraborder+4, invcol, csqr.w+(extraborder*2)-8, csqr.h+(extraborder*2)-8); //transparent X
1605 highlight_sqr(screen2, hlcol, csqr.x-extraborder, csqr.y-extraborder, csqr.w+extraborder*2, csqr.h+extraborder*2, 1); //highlight border
1606 }
1607
1608 sprintf(buf, "%02d %02d %02d %c(0x%02X %d)",c.r,c.g,c.b,separator,realcol,color);
1609 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(2*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1610
1611 strcpy(buf, get_color_name(realcol, is8b).c_str());
1612 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(1*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1613
1614 sprintf(buf, "#%02X%02X%02X", tpal[realcol].r,tpal[realcol].g,tpal[realcol].b);
1615 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(0),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1616
1617 rect(screen2, hov_prev.x, hov_prev.y, hov_prev.x+hov_prev.w-1, hov_prev.y+hov_prev.h-1, jwin_pal[jcTEXTFG]);
1618 rectfill(screen2, hov_prev.x+1, hov_prev.y+1, hov_prev.x+hov_prev.w-2, hov_prev.y+hov_prev.h-2, jwin_pal[jcTEXTBG]);
1619 rectfill(screen2, hov_prev.x+3, hov_prev.y+3, hov_prev.x+hov_prev.w-4, hov_prev.y+hov_prev.h-4, realcol);
1620 if(xcolor)
1621 little_x(screen2, hov_prev.x+1, hov_prev.y+1, invcol, hov_prev.w-2, hov_prev.h-2);
1622 }
1623 }
1624
1625 custom_vsync();
1626 blit(screen2,screen,0,0,0,0,zq_screen_w,zq_screen_w);
1627 update_tool_cursor();
1628 SCRFIX();
1629 }
1630
1631 void normalize(int32_t tile,int32_t tile2, bool rect_sel, int32_t flip)
1632 {
1633 unfloat_selection();
1634 if(tile>tile2)
1635 {
1636 zc_swap(tile, tile2);
1637 }
1638
1639 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
1640 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
1641
1642 int32_t start=tile;
1643 int32_t end=tile2;
1644
1645 // Might have top-right and bottom-left corners selected...
1646 if(rect_sel && TILECOL(tile)>TILECOL(tile2))
1647 {
1648 start=tile-(TILECOL(tile)-TILECOL(tile2));
1649 end=tile2+(TILECOL(tile)-TILECOL(tile2));
1650 }
1651
1652 for(int32_t temptile=start; temptile<=end; temptile++)
1653 {
1654 if(!rect_sel || ((TILECOL(temptile)>=left) && (TILECOL(temptile)<=left+columns-1)))
1655 {
1656 unpack_tile(newtilebuf, temptile, 0, true);
1657
1658 if(flip&1)
1659 {
1660 for(int32_t y=0; y<16; y++)
1661 {
1662 for(int32_t x=0; x<8; x++)
1663 {
1664 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[(y<<4)+15-x]);
1665 }
1666 }
1667 }
1668
1669 if(flip&2)
1670 {
1671 for(int32_t y=0; y<8; y++)
1672 {
1673 for(int32_t x=0; x<16; x++)
1674 {
1675 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[((15-y)<<4)+x]);
1676 }
1677 }
1678 }
1679
1680 pack_tile(newtilebuf,unpackbuf,temptile);
1681 }
1682 }
1683 }
1684
1685 void rotate_tile(int32_t tile, bool backward)
1686 {
1687 unfloat_selection();
1688 unpack_tile(newtilebuf, tile, 0, true);
1689 byte tempunpackbuf[256];
1690 byte tempx, tempy;
1691
1692 for(tempx=0; tempx<16; tempx++)
1693 {
1694 for(tempy=0; tempy<16; tempy++)
1695 {
1696 if(!backward)
1697 {
1698 tempunpackbuf[(tempy<<4)+tempx]=unpackbuf[((15-tempx)<<4)+tempy];
1699 }
1700 else
1701 {
1702 tempunpackbuf[((15-tempx)<<4)+tempy]=unpackbuf[(tempy<<4)+tempx];
1703 }
1704 }
1705 }
1706
1707 pack_tile(newtilebuf,tempunpackbuf,tile);
1708 }
1709
1710 static int32_t undocount=128;
1711 byte undotile[256];
1712
1713 void wrap_tile(int32_t tile, int32_t vertical, int32_t horizontal, bool clear)
1714 {
1715 byte buf[256];
1716
1717 for(int32_t i=0; i<undocount; i++)
1718 {
1719 newtilebuf[tile].data[i]=undotile[i];
1720 }
1721
1722 if(!(horizontal||vertical))
1723 {
1724 return;
1725 }
1726
1727 unpack_tile(newtilebuf, tile, 0, true);
1728
1729 for(int32_t i=0; i<256; i++)
1730 {
1731 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1732 buf[shift_ind] = unpackbuf[i];
1733 }
1734
1735 if(clear)
1736 {
1737 for(int32_t r=0; r<abs(vertical); r++)
1738 {
1739 for(int32_t c=0; c<16; c++)
1740 {
1741 buf[(vertical>0?r:15-r)*16+c]=0;
1742 }
1743 }
1744
1745 for(int32_t r=0; r<16; r++)
1746 {
1747 for(int32_t c=0; c<abs(horizontal); c++)
1748 {
1749 buf[r*16+(horizontal>0?c:15-c)]=0;
1750 }
1751 }
1752 }
1753
1754 pack_tile(newtilebuf,buf,tile);
1755 }
1756
1757 void wrap_sel_tile(int32_t vertical, int32_t horizontal)
1758 {
1759 byte buf[256];
1760
1761 if(!(horizontal||vertical))
1762 {
1763 return;
1764 }
1765
1766 memset(buf,0,256);
1767
1768 for(int32_t i=0; i<256; i++)
1769 {
1770 if(is_in_selection(i%16,i/16))
1771 {
1772 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1773 buf[shift_ind] = floatsel[i];
1774 }
1775 }
1776
1777 memcpy(floatsel,buf,256);
1778 }
1779
1780 void float_selection(int32_t tile, bool clear)
1781 {
1782 if(floating_sel) return;
1783 floating_sel = true;
1784 floating_tile = tile;
1785
1786 unpack_tile(newtilebuf, tile, 0, true);
1787
1788 for(auto q = 0; q < 256; ++q)
1789 {
1790 if(is_in_selection(q%16,q/16))
1791 {
1792 floatsel[q] = unpackbuf[q];
1793 unpackbuf[q] = clear ? 0 : c2;
1794 }
1795 else floatsel[q] = 0;
1796 }
1797
1798 pack_tile(newtilebuf,unpackbuf,tile);
1799 }
1800
1801 void unfloat_selection()
1802 {
1803 if(!floating_sel) return;
1804 floating_sel = false;
1805
1806 unpack_tile(newtilebuf, floating_tile, 0, true);
1807
1808 for(auto q = 0; q < 256; ++q)
1809 {
1810 if(floatsel[q])
1811 {
1812 unpackbuf[q] = floatsel[q];
1813 }
1814 }
1815
1816 pack_tile(newtilebuf,unpackbuf,floating_tile);
1817 floating_tile = -1;
1818 }
1819
1820 void shift_tile_colors(int32_t tile, int32_t amount, bool ignore_transparent)
1821 {
1822 if(floating_sel)
1823 {
1824 for(auto q = 0; q < 256; ++q)
1825 {
1826 if(ignore_transparent && floatsel[q]==0)
1827 continue;
1828 floatsel[q]=wrap(floatsel[q]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1829 }
1830 return;
1831 }
1832
1833 byte buf[256];
1834 unpack_tile(newtilebuf, tile, 0, true);
1835
1836 for(int32_t i=0; i<256; i++)
1837 {
1838 buf[i]=unpackbuf[i];
1839
1840 if(!is_in_selection(i&0x0F, (i&0xF0)>>4))
1841 continue;
1842
1843 if(ignore_transparent)
1844 {
1845 if(buf[i]==0)
1846 continue;
1847
1848 buf[i]=wrap(buf[i]+amount, 1, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1849 }
1850 else // Don't ignore transparent
1851 buf[i]=wrap(buf[i]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1852 }
1853
1854 pack_tile(newtilebuf,buf,tile);
1855 }
1856
1857 void clear_selection_grid()
1858 {
1859 unfloat_selection();
1860 for(int32_t x=0; x<18; ++x)
1861 {
1862 for(int32_t y=0; y<18; ++y)
1863 {
1864 selection_grid[x][y]=0;
1865 }
1866 }
1867 }
1868
1869 void invert_selection_grid()
1870 {
1871 unfloat_selection();
1872 for(int32_t x=1; x<17; ++x)
1873 {
1874 for(int32_t y=1; y<17; ++y)
1875 {
1876 selection_grid[x][y]=selection_grid[x][y]?0:1;
1877 }
1878 }
1879 }
1880
1881 void shift_selection_grid(int32_t xoffs, int32_t yoffs)
1882 {
1883 byte local_grid[16][16];
1884 memset(local_grid, 0, sizeof(local_grid));
1885 for(auto x = 0; x < 16; ++x)
1886 {
1887 for(auto y = 0; y < 16; ++y)
1888 {
1889 auto offs_x = (x+xoffs)%16, offs_y = (y+yoffs)%16;
1890 if(offs_x < 0) offs_x = (16 - abs(offs_x));
1891 if(offs_y < 0) offs_y = (16 - abs(offs_y));
1892 local_grid[offs_x][offs_y] = selection_grid[x+1][y+1]?1:0;
1893 }
1894 }
1895 for(auto x = 0; x < 16; ++x)
1896 {
1897 for(auto y = 0; y < 16; ++y)
1898 {
1899 selection_grid[x+1][y+1] = local_grid[x][y]?1:0;
1900 }
1901 }
1902 }
1903
1904 void show_edit_tile_help()
1905 {
1906 InfoDialog("Help: Tile Editor", "Hotkeys:"
1907 "\nF1: This Help Dialog"
1908 "\nEnter: Unfloat Sel / OK | Esc: Unfloat Sel / Cancel"
1909 "\nDelete: Clear Tile/Sel | Ctrl+Delete: Clear Tile"
1910 "\nA: Sel All | D: Unselect Sel | I: Invert Sel"
1911 "\nH/V: Flip | (Shift+)R: Rotate"
1912 "\n+/-: Change CSet | Ctrl +/-: Shift Colors"
1913 "\n(Ctrl+)S: Swap Colors | U/Ctrl+Z: Undo"
1914 "\nF12: Screenshot (whole screen)"
1915 "\nArrows: Shift Pixel | Ctrl+Arrows: Change Tile"
1916 "\nWhen not on Select tools, hold to swap:"
1917 "\nCtrl - Fill | Alt - Grab | Ctrl+Alt - Recolor").show();
1918 }
1919
1920 static int move_origin_x=-1, move_origin_y=-1;
1921 static int prev_x=-1, prev_y=-1;
1922 bool __pixel_draw(int x, int y, int tile, int flip)
1923 {
1924 bool ret = false;
1925 switch(tool)
1926 {
1927 case t_pen:
1928 if(flip&1) x=15-x;
1929
1930 if(flip&2) y=15-y;
1931
1932 if(is_in_selection(x,y))
1933 {
1934 if(floating_sel)
1935 {
1936 floatsel[(y<<4)+x]=(drawing==1)?c1:c2;
1937 }
1938 else
1939 {
1940 unpack_tile(newtilebuf, tile, 0, false);
1941 unpackbuf[((y<<4)+x)]=(drawing==1)?c1:c2;
1942 pack_tile(newtilebuf, unpackbuf,tile);
1943 }
1944 }
1945 break;
1946
1947 case t_fill:
1948 if(is_in_selection(x,y))
1949 {
1950 tile_floodfill(tile,x,y,(drawing==1)?c1:c2);
1951 ret = true;
1952 }
1953 break;
1954
1955 case t_recolor:
1956 if(is_in_selection(x,y))
1957 {
1958 if(floating_sel)
1959 {
1960 tf_u = floatsel[(y<<4)+x];
1961 for(int32_t i=0; i<256; i++)
1962 {
1963 if(is_in_selection(i&15,i>>4))
1964 {
1965 if(floatsel[i]==tf_u)
1966 {
1967 floatsel[i]=(drawing==1)?c1:c2;
1968 }
1969 }
1970 }
1971 }
1972 else
1973 {
1974 unpack_tile(newtilebuf, tile, 0, false);
1975 tf_u = unpackbuf[(y<<4)+x];
1976 if(tf_u != ((drawing==1)?c1:c2))
1977 {
1978 for(int32_t i=0; i<256; i++)
1979 {
1980 if(is_in_selection(i&15,i>>4))
1981 {
1982 if(unpackbuf[i]==tf_u)
1983 {
1984 unpackbuf[i]=(drawing==1)?c1:c2;
1985 }
1986 }
1987 }
1988
1989 pack_tile(newtilebuf, unpackbuf,tile);
1990 }
1991 }
1992 ret = true;
1993 }
1994 break;
1995
1996 case t_eyedropper:
1997 if(floating_sel)
1998 memcpy(unpackbuf, floatsel, 256);
1999 else unpack_tile(newtilebuf, tile, 0, false);
2000
2001 if(gui_mouse_b()&1)
2002 {
2003 c1=unpackbuf[((y<<4)+x)];
2004 }
2005
2006 if(gui_mouse_b()&2)
2007 {
2008 c2=unpackbuf[((y<<4)+x)];
2009 }
2010 break;
2011
2012 case t_move:
2013 if((prev_x!=x)||(prev_y!=y))
2014 {
2015 if(has_selection())
2016 {
2017 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2018 wrap_sel_tile(y-prev_y, x-prev_x);
2019 shift_selection_grid(x-prev_x, y-prev_y);
2020 }
2021 else wrap_tile(tile, y-move_origin_y, x-move_origin_x, drawing==2);
2022 prev_x=x;
2023 prev_y=y;
2024 }
2025 break;
2026
2027 case t_select:
2028 unfloat_selection();
2029 if(flip&1) x=15-x;
2030
2031 if(flip&2) y=15-y;
2032
2033 if(selecting_x1==-1||selecting_y1==-1)
2034 {
2035 selecting_x1=x;
2036 selecting_y1=y;
2037 }
2038 else
2039 {
2040 selecting_x2=x;
2041 selecting_y2=y;
2042 }
2043 break;
2044
2045 case t_wand:
2046 unfloat_selection();
2047 if(flip&1) x=15-x;
2048
2049 if(flip&2) y=15-y;
2050
2051 switch(select_mode)
2052 {
2053 case 0:
2054 clear_selection_grid();
2055 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2056 break;
2057
2058 case 1:
2059 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2060 break;
2061
2062 case 2:
2063 remove_color_from_selection(unpackbuf[((y<<4)+x)]);
2064 break;
2065
2066 case 3:
2067 intersect_color_with_selection(unpackbuf[((y<<4)+x)]);
2068 break;
2069 }
2070
2071 ret = true;
2072 break;
2073 }
2074 return ret;
2075 }
2076 void edit_tile(int32_t tile,int32_t flip,int32_t &cs)
2077 {
2078 popup_zqdialog_start();
2079 FONT* oldfont = font;
2080 font = get_custom_font(CFONT_DLG);
2081 edit_button.h = ok_button.h = cancel_button.h = 12+text_height(font);
2082 status_info.yscale = text_height(font);
2083 status_info.y = 308-(status_info.h*status_info.yscale);
2084 hover_info.yscale = status_info.yscale;
2085 hover_info.y = 338-(hover_info.h*hover_info.yscale);
2086 go();
2087 undocount = tilesize(newtilebuf[tile].format);
2088 clear_selection_grid();
2089 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2090
2091 tthighlight = zc_get_config("ZQ_GUI","tile_edit_fancyhighlight",1);
2092 showcolortip = zc_get_config("ZQ_GUI","tile_edit_colornames",1);
2093
2094 PALETTE tpal;
2095 byte oldtile[256];
2096
2097 memset(&tpal, 0, sizeof(PALETTE));
2098 memset(oldtile, 0, 256);
2099
2100 for(int32_t i=0; i<undocount; i++)
2101 {
2102 oldtile[i]=undotile[i]=newtilebuf[tile].data[i];
2103 }
2104 byte undoselgrid[16][16];
2105 for(auto x = 0; x < 16; ++x)
2106 for(auto y = 0; y < 16; ++y)
2107 undoselgrid[x][y] = selection_grid[x+1][y+1];
2108 for(auto q = 0; q < 256; ++q)
2109 {
2110 floatsel[q] = 0;
2111 undofloatsel[q] = 0;
2112 floating_sel = false;
2113 undo_is_floatsel = false;
2114 }
2115
2116 int32_t tile_x=-1, tile_y=-1;
2117 int32_t temp_x=-1, temp_y=-1;
2118 bool bdown=false;
2119 int32_t done=0;
2120 drawing=0;
2121 tool_cur = -1;
2122
2123 get_palette(tpal);
2124
2125 if(newtilebuf[tile].format==tf4Bit)
2126 {
2127 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2128 }
2129 else
2130 {
2131 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2132 }
2133
2134 custom_vsync();
2135 zc_set_palette(tpal);
2136 draw_edit_scr(tile,flip,cs,oldtile, true);
2137
2138 while(gui_mouse_b())
2139 {
2140 /* do nothing */
2141 rest(1);
2142 }
2143
2144 move_origin_x=-1;
2145 move_origin_y=-1;
2146 prev_x=-1;
2147 prev_y=-1;
2148
2149
2150
2151 byte selection_pattern_source[8][8]=
2152 {
2153 {1, 1, 1, 1, 0, 0, 0, 0},
2154 {1, 1, 1, 0, 0, 0, 0, 1},
2155 {1, 1, 0, 0, 0, 0, 1, 1},
2156 {1, 0, 0, 0, 0, 1, 1, 1},
2157 {0, 0, 0, 0, 1, 1, 1, 1},
2158 {0, 0, 0, 1, 1, 1, 1, 0},
2159 {0, 0, 1, 1, 1, 1, 0, 0},
2160 {0, 1, 1, 1, 1, 0, 0, 0},
2161 };
2162
2163 byte selecting_pattern_source[8][8]=
2164 {
2165 {1, 1, 0, 0, 0, 0, 1, 1},
2166 {1, 0, 0, 0, 0, 1, 1, 1},
2167 {0, 0, 0, 0, 1, 1, 1, 1},
2168 {0, 0, 0, 1, 1, 1, 1, 0},
2169 {0, 0, 1, 1, 1, 1, 0, 0},
2170 {0, 1, 1, 1, 1, 0, 0, 0},
2171 {1, 1, 1, 1, 0, 0, 0, 0},
2172 {1, 1, 1, 0, 0, 0, 0, 1},
2173 };
2174
2175 byte intersection_pattern_source[8][8]=
2176 {
2177 {0, 0, 1, 1, 0, 0, 1, 1},
2178 {0, 1, 1, 0, 0, 1, 1, 0},
2179 {1, 1, 0, 0, 1, 1, 0, 0},
2180 {1, 0, 0, 1, 1, 0, 0, 1},
2181 {0, 0, 1, 1, 0, 0, 1, 1},
2182 {0, 1, 1, 0, 0, 1, 1, 0},
2183 {1, 1, 0, 0, 1, 1, 0, 0},
2184 {1, 0, 0, 1, 1, 0, 0, 1},
2185 };
2186
2187 selection_pattern=create_bitmap_ex(8, 8, 8);
2188
2189 for(int32_t x=0; x<8; ++x)
2190 {
2191 for(int32_t y=0; y<8; ++y)
2192 {
2193 selection_pattern->line[y][x]=selection_pattern_source[x][y]?vc(0):vc(15);
2194 }
2195 }
2196
2197 selecting_pattern=create_bitmap_ex(8, 8, 8);
2198
2199 for(int32_t x=0; x<8; ++x)
2200 {
2201 for(int32_t y=0; y<8; ++y)
2202 {
2203 selecting_pattern->line[y][x]=selecting_pattern_source[x][y]?vc(0):vc(15);
2204 }
2205 }
2206
2207 intersection_pattern=create_bitmap_ex(8, 8, 8);
2208
2209 for(int32_t x=0; x<8; ++x)
2210 {
2211 for(int32_t y=0; y<8; ++y)
2212 {
2213 intersection_pattern->line[y][x]=intersection_pattern_source[x][y]?vc(0):vc(15);
2214 }
2215 }
2216
2217 do
2218 {
2219 HANDLE_CLOSE_ZQDLG();
2220 if(exiting_program) break;
2221 int32_t temp_mouse_x=gui_mouse_x();
2222 int32_t temp_mouse_y=gui_mouse_y();
2223 rest(4);
2224 bool redraw=false;
2225 bool did_wand_select=false;
2226
2227 if(keypressed())
2228 {
2229 bool ctrl = CHECK_CTRL_CMD;
2230 int k = readkey()>>8;
2231 switch(k)
2232 {
2233 case KEY_F1:
2234 show_edit_tile_help();
2235 break;
2236 case KEY_ENTER_PAD:
2237 case KEY_ENTER:
2238 if(floating_sel)
2239 unfloat_selection();
2240 else done=2;
2241 break;
2242
2243 case KEY_ESC:
2244 if(floating_sel)
2245 unfloat_selection();
2246 else if(has_selection())
2247 clear_selection_grid();
2248 else done=1;
2249 break;
2250
2251 case KEY_DEL:
2252 {
2253 unpack_tile(newtilebuf, tile, 0, false);
2254 bool all = CHECK_CTRL_CMD || !has_selection();
2255 bool canDel = false;
2256 if(all)
2257 {
2258 //Check all
2259 for(auto q = 0; q < 256; ++q)
2260 if(unpackbuf[q])
2261 {
2262 canDel = true;
2263 break;
2264 }
2265 }
2266 else
2267 {
2268 //Check selection
2269 for(auto x = 0; x < 16; ++x)
2270 for(auto y = 0; y < 16; ++y)
2271 if(is_in_selection(x,y))
2272 if(unpackbuf[(y<<4)+x])
2273 {
2274 canDel = true;
2275 break;
2276 }
2277 }
2278 if(!canDel) break; //don't delete (and thus reset undo) if nothing would change!
2279
2280 for(int32_t i=0; i<undocount; i++)
2281 {
2282 undotile[i]=newtilebuf[tile].data[i];
2283 }
2284 for(auto x = 0; x < 16; ++x)
2285 for(auto y = 0; y < 16; ++y)
2286 undoselgrid[x][y] = selection_grid[x+1][y+1];
2287 for(auto q = 0; q < 256; ++q)
2288 undofloatsel[q] = floatsel[q];
2289 undo_is_floatsel = floating_sel;
2290
2291 if(CHECK_CTRL_CMD || !has_selection())
2292 {
2293 //Delete all
2294 for(auto q = 0; q < 256; ++q)
2295 {
2296 unpackbuf[q] = 0;
2297 floatsel[q] = 0;
2298 }
2299 }
2300 else
2301 {
2302 //Delete selection
2303 for(auto x = 0; x < 16; ++x)
2304 for(auto y = 0; y < 16; ++y)
2305 {
2306 if(floating_sel)
2307 {
2308 floatsel[x+(y<<4)] = 0;
2309 }
2310 else if(is_in_selection(x,y))
2311 {
2312 unpackbuf[(y<<4)+x] = 0;
2313 }
2314 }
2315 }
2316 pack_tile(newtilebuf, unpackbuf, tile);
2317 redraw=true;
2318 }
2319 break;
2320
2321 case KEY_A:
2322 clear_selection_grid();
2323 invert_selection_grid();
2324 redraw=true;
2325 break;
2326
2327 case KEY_D:
2328 clear_selection_grid();
2329 redraw=true;
2330 break;
2331
2332 case KEY_I:
2333 invert_selection_grid();
2334 redraw=true;
2335 break;
2336
2337 case KEY_H:
2338 flip^=1;
2339 normalize(tile,tile,0,flip);
2340 flip=0;
2341 redraw=true;
2342 break;
2343
2344 case KEY_V:
2345 flip^=2;
2346 normalize(tile,tile,0,flip);
2347 flip=0;
2348 redraw=true;
2349 break;
2350
2351 case KEY_F12:
2352 onSnapshot();
2353 break;
2354
2355 case KEY_R:
2356 {
2357 //if(CHECK_CTRL_CMD))
2358 // {
2359 //do_recolor(tile); redraw=true; saved=false;
2360 // }
2361 //else
2362 // {
2363 go_tiles();
2364 rotate_tile(tile,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
2365 redraw=true;
2366 saved=false;
2367 break;
2368 }
2369
2370 case KEY_EQUALS:
2371 case KEY_PLUS_PAD:
2372 {
2373 if(CHECK_CTRL_CMD ||
2374 key[KEY_ALT] || key[KEY_ALTGR])
2375 {
2376 for(int32_t i=0; i<undocount; i++)
2377 undotile[i]=newtilebuf[tile].data[i];
2378 for(auto x = 0; x < 16; ++x)
2379 for(auto y = 0; y < 16; ++y)
2380 undoselgrid[x][y] = selection_grid[x+1][y+1];
2381 for(auto q = 0; q < 256; ++q)
2382 undofloatsel[q] = floatsel[q];
2383 undo_is_floatsel = floating_sel;
2384
2385 if(key[KEY_ALT] || key[KEY_ALTGR])
2386 shift_tile_colors(tile, 16, false);
2387 else
2388 shift_tile_colors(tile, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2389 }
2390 else
2391 cs = (cs<13) ? cs+1:0;
2392
2393 redraw=true;
2394 break;
2395 }
2396
2397 case KEY_MINUS:
2398 case KEY_MINUS_PAD:
2399 {
2400 if(CHECK_CTRL_CMD ||
2401 key[KEY_ALT] || key[KEY_ALTGR])
2402 {
2403 for(int32_t i=0; i<undocount; i++)
2404 undotile[i]=newtilebuf[tile].data[i];
2405 for(auto x = 0; x < 16; ++x)
2406 for(auto y = 0; y < 16; ++y)
2407 undoselgrid[x][y] = selection_grid[x+1][y+1];
2408 for(auto q = 0; q < 256; ++q)
2409 undofloatsel[q] = floatsel[q];
2410 undo_is_floatsel = floating_sel;
2411
2412 if(key[KEY_ALT] || key[KEY_ALTGR])
2413 shift_tile_colors(tile, -16, false);
2414 else
2415 shift_tile_colors(tile, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2416 }
2417 else
2418 cs = (cs>0) ? cs-1:13;
2419
2420 redraw=true;
2421 break;
2422 }
2423
2424 case KEY_SPACE:
2425 gridmode=(gridmode+1)%gm_max;
2426 redraw=true;
2427 break;
2428
2429 case KEY_Z:
2430 if(!ctrl)
2431 break;
2432 //Ctrl+Z == undo
2433 [[fallthrough]];
2434 case KEY_U:
2435 for(int32_t i=0; i<undocount; i++)
2436 zc_swap(undotile[i],newtilebuf[tile].data[i]);
2437
2438 for(auto x = 0; x < 16; ++x)
2439 for(auto y = 0; y < 16; ++y)
2440 zc_swap(selection_grid[x+1][y+1], undoselgrid[x][y]);
2441
2442 for(auto q = 0; q < 256; ++q)
2443 zc_swap(undofloatsel[q], floatsel[q]);
2444 zc_swap(undo_is_floatsel, floating_sel);
2445
2446 redraw=true;
2447 break;
2448
2449 case KEY_S:
2450 if(CHECK_CTRL_CMD)
2451 {
2452 for(int32_t i=0; i<undocount; i++)
2453 {
2454 undotile[i]=newtilebuf[tile].data[i];
2455 }
2456 for(auto x = 0; x < 16; ++x)
2457 for(auto y = 0; y < 16; ++y)
2458 undoselgrid[x][y] = selection_grid[x+1][y+1];
2459 for(auto q = 0; q < 256; ++q)
2460 undofloatsel[q] = floatsel[q];
2461 undo_is_floatsel = floating_sel;
2462
2463 unpack_tile(newtilebuf, tile, 0, false);
2464
2465 if(has_selection())
2466 {
2467 for(int32_t i=0; i<256; i++)
2468 {
2469 if(!is_in_selection(i%16,i/16))
2470 continue;
2471 if(unpackbuf[i]==c1)
2472 {
2473 unpackbuf[i]=c2;
2474 }
2475 else if(unpackbuf[i]==c2)
2476 {
2477 unpackbuf[i]=c1;
2478 }
2479 if(floating_sel)
2480 {
2481 if(floatsel[i]==c1)
2482 {
2483 floatsel[i]=c2;
2484 }
2485 else if(floatsel[i]==c2)
2486 {
2487 floatsel[i]=c1;
2488 }
2489 }
2490 }
2491 }
2492 else
2493 {
2494 for(int32_t i=0; i<256; i++)
2495 {
2496 if(unpackbuf[i]==c1)
2497 {
2498 unpackbuf[i]=c2;
2499 }
2500 else if(unpackbuf[i]==c2)
2501 {
2502 unpackbuf[i]=c1;
2503 }
2504 }
2505 }
2506
2507 pack_tile(newtilebuf, unpackbuf,tile);
2508 }
2509
2510 zc_swap(c1,c2);
2511 redraw=true;
2512 break;
2513
2514 case KEY_UP:
2515 if(CHECK_CTRL_CMD)
2516 {
2517 unfloat_selection();
2518 tile=zc_max(0,tile-TILES_PER_ROW);
2519 undocount = tilesize(newtilebuf[tile].format);
2520
2521 for(int32_t i=0; i<undocount; i++)
2522 {
2523 undotile[i]=newtilebuf[tile].data[i];
2524 oldtile[i]=undotile[i];
2525 }
2526
2527 redraw=true;
2528 }
2529 else
2530 {
2531 for(int32_t i=0; i<undocount; i++)
2532 {
2533 undotile[i]=newtilebuf[tile].data[i];
2534 }
2535 for(auto x = 0; x < 16; ++x)
2536 for(auto y = 0; y < 16; ++y)
2537 undoselgrid[x][y] = selection_grid[x+1][y+1];
2538 for(auto q = 0; q < 256; ++q)
2539 undofloatsel[q] = floatsel[q];
2540 undo_is_floatsel = floating_sel;
2541 if(has_selection())
2542 {
2543 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2544 wrap_sel_tile(-1, 0);
2545 shift_selection_grid(0, -1);
2546 }
2547 else wrap_tile(tile, -1, 0, false);
2548 redraw=true;
2549 }
2550 break;
2551
2552 case KEY_DOWN:
2553 if(CHECK_CTRL_CMD)
2554 {
2555 unfloat_selection();
2556 tile=zc_min(tile+TILES_PER_ROW,NEWMAXTILES-1);
2557 undocount = tilesize(newtilebuf[tile].format);
2558
2559 for(int32_t i=0; i<undocount; i++)
2560 {
2561 undotile[i]=newtilebuf[tile].data[i];
2562 oldtile[i]=undotile[i];
2563 }
2564
2565 redraw=true;
2566 }
2567 else
2568 {
2569 for(int32_t i=0; i<undocount; i++)
2570 {
2571 undotile[i]=newtilebuf[tile].data[i];
2572 }
2573 for(auto x = 0; x < 16; ++x)
2574 for(auto y = 0; y < 16; ++y)
2575 undoselgrid[x][y] = selection_grid[x+1][y+1];
2576 for(auto q = 0; q < 256; ++q)
2577 undofloatsel[q] = floatsel[q];
2578 undo_is_floatsel = floating_sel;
2579 if(has_selection())
2580 {
2581 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2582 wrap_sel_tile(1, 0);
2583 shift_selection_grid(0, 1);
2584 }
2585 else wrap_tile(tile, 1, 0, false);
2586 redraw=true;
2587 }
2588 break;
2589
2590 case KEY_LEFT:
2591 if(CHECK_CTRL_CMD)
2592 {
2593 unfloat_selection();
2594 tile=zc_max(0,tile-1);
2595 undocount = tilesize(newtilebuf[tile].format);
2596
2597 for(int32_t i=0; i<undocount; i++)
2598 {
2599 undotile[i]=newtilebuf[tile].data[i];
2600 oldtile[i]=undotile[i];
2601 }
2602
2603 redraw=true;
2604 }
2605 else
2606 {
2607 for(int32_t i=0; i<undocount; i++)
2608 {
2609 undotile[i]=newtilebuf[tile].data[i];
2610 }
2611 for(auto x = 0; x < 16; ++x)
2612 for(auto y = 0; y < 16; ++y)
2613 undoselgrid[x][y] = selection_grid[x+1][y+1];
2614 for(auto q = 0; q < 256; ++q)
2615 undofloatsel[q] = floatsel[q];
2616 undo_is_floatsel = floating_sel;
2617 if(has_selection())
2618 {
2619 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2620 wrap_sel_tile(0, -1);
2621 shift_selection_grid(-1, 0);
2622 }
2623 else wrap_tile(tile, 0, -1, false);
2624 redraw=true;
2625 }
2626 break;
2627
2628 case KEY_RIGHT:
2629 if(CHECK_CTRL_CMD)
2630 {
2631 unfloat_selection();
2632 tile=zc_min(tile+1, NEWMAXTILES-1);
2633 undocount = tilesize(newtilebuf[tile].format);
2634
2635 for(int32_t i=0; i<undocount; i++)
2636 {
2637 undotile[i]=newtilebuf[tile].data[i];
2638 oldtile[i]=undotile[i];
2639 }
2640
2641 redraw=true;
2642 }
2643 else
2644 {
2645 for(int32_t i=0; i<undocount; i++)
2646 {
2647 undotile[i]=newtilebuf[tile].data[i];
2648 }
2649 for(auto x = 0; x < 16; ++x)
2650 for(auto y = 0; y < 16; ++y)
2651 undoselgrid[x][y] = selection_grid[x+1][y+1];
2652 for(auto q = 0; q < 256; ++q)
2653 undofloatsel[q] = floatsel[q];
2654 undo_is_floatsel = floating_sel;
2655 if(has_selection())
2656 {
2657 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2658 wrap_sel_tile(0, 1);
2659 shift_selection_grid(1, 0);
2660 }
2661 else wrap_tile(tile, 0, 1, false);
2662 redraw=true;
2663 }
2664 break;
2665 case KEY_0: case KEY_1: case KEY_2: case KEY_3:
2666 case KEY_4: case KEY_5: case KEY_6: case KEY_7:
2667 case KEY_8: case KEY_9:
2668 case KEY_0_PAD: case KEY_1_PAD: case KEY_2_PAD: case KEY_3_PAD:
2669 case KEY_4_PAD: case KEY_5_PAD: case KEY_6_PAD: case KEY_7_PAD:
2670 case KEY_8_PAD: case KEY_9_PAD:
2671 {
2672 int t = k - ((k>KEY_9) ? KEY_1_PAD : KEY_1);
2673 if(unsigned(t) < t_max)
2674 {
2675 if(old_tool != -1)
2676 old_tool = t;
2677 else tool = t;
2678 }
2679 break;
2680 }
2681 case KEY_TAB:
2682 {
2683 if(key_shifts & KB_CTRL_CMD_FLAG)
2684 {
2685 xmode = (xmode+1)%XMODE_MAX;
2686 if(!xmode)
2687 bgmode = (bgmode+1)%BGMODE_MAX;
2688 }
2689 else if(key_shifts & KB_SHIFT_FLAG)
2690 hide_grid = !hide_grid;
2691 else show_quartgrid = !show_quartgrid;
2692 redraw = true;
2693 break;
2694 }
2695 }
2696 clear_keybuf();
2697 }
2698
2699 if(!gui_mouse_b())
2700 {
2701 if(is_selecting())
2702 {
2703 unfloat_selection();
2704 int32_t x1=zc_min(selecting_x1,selecting_x2);
2705 int32_t x2=zc_max(selecting_x1,selecting_x2);
2706 int32_t y1=zc_min(selecting_y1,selecting_y2);
2707 int32_t y2=zc_max(selecting_y1,selecting_y2);
2708
2709 if(select_mode==0)
2710 {
2711 clear_selection_grid();
2712 }
2713
2714 for(int32_t x=x1; x<=x2; ++x)
2715 {
2716 for(int32_t y=y1; y<=y2; ++y)
2717 {
2718 selection_grid[x+1][y+1]=((select_mode<2)?(1):(((select_mode==2)?(0):(selection_grid[x+1][y+1]))));
2719 }
2720 }
2721
2722 if(select_mode==3)
2723 {
2724 for(int32_t y=0; y<16; ++y)
2725 {
2726 for(int32_t x=0; x<x1; ++x)
2727 {
2728 selection_grid[x+1][y+1]=0;
2729 }
2730
2731 for(int32_t x=x2+1; x<16; ++x)
2732 {
2733 selection_grid[x+1][y+1]=0;
2734 }
2735 }
2736
2737 for(int32_t x=x1; x<=x2; ++x)
2738 {
2739 for(int32_t y=0; y<y1; ++y)
2740 {
2741 selection_grid[x+1][y+1]=0;
2742 }
2743
2744 for(int32_t y=y2+1; y<16; ++y)
2745 {
2746 selection_grid[x+1][y+1]=0;
2747 }
2748 }
2749 }
2750 }
2751
2752 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2753 did_wand_select=false;
2754 }
2755
2756 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
2757 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2758 bool ctrl=CHECK_CTRL_CMD;
2759 static int32_t last_tool_val = 0;
2760
2761 if(tool==t_select||tool==t_wand)
2762 {
2763 if(!drawing)
2764 {
2765 int32_t type=0;
2766
2767 if(has_selection())
2768 {
2769 if(shift)
2770 {
2771 type+=1;
2772 }
2773
2774 if(alt)
2775 {
2776 type+=2;
2777 }
2778 }
2779
2780 if(type!=select_mode)
2781 {
2782 select_mode=type;
2783
2784 if(isinRect(temp_mouse_x,temp_mouse_y-(tool==t_fill ? (14) : 0),zoomtile.x,zoomtile.y,zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2785 set_tool_sprite(tool,type);
2786 }
2787 }
2788 }
2789 else if(alt||ctrl)
2790 {
2791 if(old_tool==-1)
2792 {
2793 old_tool = tool;
2794 tool_cur = -1;
2795 }
2796 if(alt&&ctrl)
2797 tool = t_recolor;
2798 else if(alt)
2799 tool = t_eyedropper;
2800 else tool = t_fill;
2801 }
2802 else if(old_tool!=-1)
2803 {
2804 tool = old_tool;
2805 old_tool = -1;
2806 tool_cur = -1;
2807 redraw = true;
2808 }
2809 if(last_tool_val != tool)
2810 {
2811 redraw = true;
2812 tool_cur = -1;
2813 update_tool_cursor();
2814 last_tool_val = tool;
2815 }
2816
2817 if(!bdown)
2818 {
2819 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2820 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2821 }
2822
2823 if(gui_mouse_b()==1 && !bdown) //pressed the left mouse button
2824 {
2825 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2826 {
2827 if(tool==t_move || tool==t_fill)
2828 {
2829 set_tool_sprite(tool,1);
2830
2831 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2832 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2833 }
2834
2835 for(int32_t i=0; i<undocount; i++)
2836 {
2837 undotile[i]=newtilebuf[tile].data[i];
2838 }
2839 for(auto x = 0; x < 16; ++x)
2840 for(auto y = 0; y < 16; ++y)
2841 undoselgrid[x][y] = selection_grid[x+1][y+1];
2842 for(auto q = 0; q < 256; ++q)
2843 undofloatsel[q] = floatsel[q];
2844 undo_is_floatsel = floating_sel;
2845
2846 drawing=1;
2847 }
2848
2849 if(ok_button.rect(temp_mouse_x,temp_mouse_y))
2850 {
2851 if(do_text_button(ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK"))
2852 {
2853 done=2;
2854 }
2855 }
2856
2857 if(cancel_button.rect(temp_mouse_x,temp_mouse_y))
2858 {
2859 if(do_text_button(cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel"))
2860 {
2861 done=1;
2862 }
2863 }
2864
2865 if(edit_button.rect(temp_mouse_x,temp_mouse_y))
2866 {
2867 if(do_text_button(edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal"))
2868 {
2869 colors_menu.pop(edit_button.x+2,edit_button.y-40);
2870 get_palette(tpal);
2871
2872 if(newtilebuf[tile].format==tf4Bit)
2873 {
2874 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2875 }
2876 else
2877 {
2878 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2879 }
2880
2881 redraw=true;
2882 }
2883 }
2884
2885 int sqr_clicked;
2886 if(show_quartgrid && qgrid_tool(tool))
2887 {
2888 sqr_clicked = reflbtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2889 if(sqr_clicked > -1)
2890 {
2891 auto& sqr = reflbtn_grid.subsquare(sqr_clicked);
2892 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[sqr_clicked]))
2893 refl_flags ^= (1<<sqr_clicked);
2894 }
2895 }
2896 sqr_clicked = xmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2897 if(sqr_clicked > -1)
2898 {
2899 auto& sqr = xmodebtn_grid.subsquare(sqr_clicked);
2900 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[sqr_clicked]))
2901 xmode = sqr_clicked;
2902 }
2903 sqr_clicked = bgmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2904 if(sqr_clicked > -1)
2905 {
2906 auto& sqr = bgmodebtn_grid.subsquare(sqr_clicked);
2907 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[sqr_clicked]))
2908 bgmode = sqr_clicked;
2909 }
2910
2911 if(showcolortip)
2912 {
2913 if(color_info.rect(temp_mouse_x,temp_mouse_y))
2914 {
2915 showcolortip = 0;
2916 zc_set_config("ZQ_GUI","tile_edit_colornames",0);
2917 }
2918 }
2919 else
2920 {
2921 if(color_info_btn.rect(temp_mouse_x,temp_mouse_y))
2922 {
2923 if(do_text_button(color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,"Show Colors"))
2924 {
2925 showcolortip = 1;
2926 zc_set_config("ZQ_GUI","tile_edit_colornames",1);
2927 redraw=true;
2928 }
2929 }
2930 }
2931
2932 if(hlcbox.rect(temp_mouse_x,temp_mouse_y))
2933 {
2934 if(do_checkbox(screen2,hlcbox.x,hlcbox.y,hlcbox.w,hlcbox.h,tthighlight))
2935 {
2936 zc_set_config("ZQ_GUI","tile_edit_fancyhighlight",tthighlight);
2937 redraw=true;
2938 }
2939 }
2940 if(quartgrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2941 {
2942 if(do_checkbox(screen2,quartgrid_cbox.x,quartgrid_cbox.y,quartgrid_cbox.w,quartgrid_cbox.h,show_quartgrid))
2943 redraw=true;
2944 }
2945 if(hidegrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2946 {
2947 if(do_checkbox(screen2,hidegrid_cbox.x,hidegrid_cbox.y,hidegrid_cbox.w,hidegrid_cbox.h,hide_grid))
2948 redraw=true;
2949 }
2950
2951 switch(newtilebuf[tile].format)
2952 {
2953 case tf4Bit:
2954 {
2955 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
2956 if(ind > -1)
2957 {
2958 c1 = ind;
2959 redraw=true;
2960 }
2961 break;
2962 }
2963 case tf8Bit:
2964 {
2965 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
2966 if(ind > -1)
2967 {
2968 c1 = ind;
2969 redraw=true;
2970 }
2971 break;
2972 }
2973 }
2974
2975
2976 int32_t newtool = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
2977 if(newtool > -1 && newtool < t_max)
2978 {
2979 tool=newtool;
2980 redraw=true;
2981 }
2982
2983 if(x_btn.rect(temp_mouse_x,temp_mouse_y))
2984 {
2985 if(do_x_button(screen, x_btn.x, x_btn.y))
2986 {
2987 done=1;
2988 }
2989 }
2990 if(info_btn.rect(temp_mouse_x,temp_mouse_y))
2991 {
2992 if(do_question_button(screen, info_btn.x, info_btn.y))
2993 {
2994 show_edit_tile_help();
2995 }
2996 }
2997
2998 bdown=true;
2999 }
3000
3001 if(gui_mouse_b()&2 && !bdown) //pressed the right mouse button
3002 {
3003 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3004 {
3005 if(tool==t_move || tool==t_fill)
3006 {
3007 set_tool_sprite(tool,1);
3008
3009 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
3010 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
3011 }
3012
3013 for(int32_t i=0; i<undocount; i++)
3014 {
3015 undotile[i]=newtilebuf[tile].data[i];
3016 }
3017 for(auto x = 0; x < 16; ++x)
3018 for(auto y = 0; y < 16; ++y)
3019 undoselgrid[x][y] = selection_grid[x+1][y+1];
3020 for(auto q = 0; q < 256; ++q)
3021 undofloatsel[q] = floatsel[q];
3022 undo_is_floatsel = floating_sel;
3023
3024 drawing=2;
3025 }
3026
3027 switch(newtilebuf[tile].format)
3028 {
3029 case tf4Bit:
3030 {
3031 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
3032 if(ind > -1)
3033 {
3034 c2 = ind;
3035 redraw=true;
3036 }
3037 break;
3038 }
3039 case tf8Bit:
3040 {
3041 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
3042 if(ind > -1)
3043 {
3044 c2 = ind;
3045 redraw=true;
3046 }
3047 break;
3048 }
3049 }
3050
3051 bdown=true;
3052 }
3053
3054 if(bdown&&!gui_mouse_b()) //released the buttons
3055 {
3056 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3057 {
3058 if(tool==t_move || tool==t_fill)
3059 {
3060 set_tool_sprite(tool,0);
3061 }
3062 }
3063 }
3064
3065 if(drawing && zoomtile.rect(temp_mouse_x,temp_mouse_y)) //inside the zoomed tile window
3066 {
3067 int32_t ind = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3068 int32_t x=ind%zoomtile.w;
3069 int32_t y=ind/zoomtile.w;
3070
3071 bool reset_draw = false;
3072
3073 if(__pixel_draw(x,y,tile,flip))
3074 reset_draw = true;
3075 if(show_quartgrid)
3076 {
3077 auto tmp_sel_mode = select_mode;
3078 if(tool == t_wand && select_mode == 0)
3079 select_mode = 1;
3080 if(qgrid_tool(tool))
3081 {
3082 if(refl_flags & (1<<REFL_HFLIP))
3083 if(__pixel_draw(15-x,y,tile,flip))
3084 reset_draw = true;
3085 if(refl_flags & (1<<REFL_VFLIP))
3086 if(__pixel_draw(x,15-y,tile,flip))
3087 reset_draw = true;
3088 //Diagonal flip and 180° rotation are the same!
3089 if(refl_flags & ((1<<REFL_DBLFLIP)|(1<<REFL_180)))
3090 if(__pixel_draw(15-x,15-y,tile,flip))
3091 reset_draw = true;
3092 if(refl_flags & (1<<REFL_90CW))
3093 if(__pixel_draw(15-y,x,tile,flip))
3094 reset_draw = true;
3095 if(refl_flags & (1<<REFL_90CCW))
3096 if(__pixel_draw(y,15-x,tile,flip))
3097 reset_draw = true;
3098 }
3099 select_mode = tmp_sel_mode;
3100 }
3101
3102 if(reset_draw)
3103 drawing = 0;
3104 redraw=true;
3105 }
3106
3107 if(gui_mouse_b()==0)
3108 {
3109 bdown=false;
3110 drawing=0;
3111 }
3112
3113 temp_x=(gui_mouse_x()-zoomtile.x)/zoomtile.xscale;
3114 temp_y=(gui_mouse_y()-zoomtile.y)/zoomtile.yscale;
3115
3116 {
3117 tile_x=temp_x;
3118 tile_y=temp_y;
3119 redraw=true;
3120 }
3121
3122 const char *toolnames[t_max]=
3123 {
3124 "Pen\nDraw Single Pixels", "Fill\nCtrl", "Replace Color\nCtrl+Alt", "Grab Color\nAlt", "Move\nMove Selections", "Select Pixels", "Select Color"
3125 };
3126
3127 int32_t toolbtn = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
3128 if(toolbtn > -1 && toolbtn < t_max)
3129 {
3130 int32_t column = toolbtn%tool_btns.w;
3131 int32_t row = toolbtn/tool_btns.w;
3132
3133 update_tooltip(temp_mouse_x,temp_mouse_y,tool_btns.x+(column*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale, toolnames[toolbtn]);
3134 redraw=true;
3135 }
3136 /* Highlight the hovered pixel? Eh, maybe too much?
3137 int32_t hov_pix = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3138 if(hov_pix > -1)
3139 {
3140 int32_t column = hov_pix%zoomtile.w;
3141 int32_t row = hov_pix/zoomtile.w;
3142
3143 update_tooltip(temp_mouse_x,temp_mouse_y,zoomtile.x+(column*zoomtile.xscale),zoomtile.y+(row*zoomtile.yscale),zoomtile.xscale,zoomtile.yscale, NULL);
3144 redraw=true;
3145 }*/
3146
3147 if(redraw)
3148 {
3149 custom_vsync();
3150 draw_edit_scr(tile,flip,cs,oldtile, false);
3151 }
3152 else
3153 {
3154 bool hs=has_selection();
3155
3156 if(hs)
3157 {
3158 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
3159 }
3160
3161 custom_vsync();
3162
3163 if(hs)
3164 {
3165 // blit(screen2, screen, 79, 31, 79, 31, 129, 129);
3166 blit(screen2, screen, zoomtile.x-1,zoomtile.y-1, zoomtile.x-1,zoomtile.y-1, (zoomtile.w*zoomtile.xscale)+1, (zoomtile.h*zoomtile.yscale)+1);
3167 }
3168
3169 update_tool_cursor();
3170 SCRFIX();
3171 }
3172
3173 }
3174 while(!done);
3175
3176 unfloat_selection();
3177 clear_selection_grid();
3178
3179 while(gui_mouse_b())
3180 {
3181 /* do nothing */
3182 rest(1);
3183 }
3184
3185 if(done==1)
3186 {
3187 for(int32_t i=0; i<undocount; i++)
3188 {
3189 newtilebuf[tile].data[i]=oldtile[i];
3190 }
3191 }
3192 else
3193 {
3194 byte *buf = new byte[undocount];
3195
3196 // put back old tile
3197 for(int32_t i=0; i<undocount; i++)
3198 {
3199 buf[i] = newtilebuf[tile].data[i];
3200 newtilebuf[tile].data[i] = oldtile[i];
3201 }
3202
3203 // go
3204 go_tiles();
3205
3206 // replace old tile with new one again
3207 for(int32_t i=0; i<undocount; i++)
3208 {
3209 newtilebuf[tile].data[i] = buf[i];
3210 }
3211
3212 saved=false;
3213
3214 if(buf!=NULL)
3215 {
3216 delete[] buf;
3217 }
3218 }
3219
3220 MouseSprite::set(ZQM_NORMAL);
3221 register_blank_tiles();
3222 register_used_tiles();
3223 clear_tooltip();
3224 comeback();
3225 destroy_bitmap(selection_pattern);
3226 destroy_bitmap(selecting_pattern);
3227 destroy_bitmap(intersection_pattern);
3228 font = oldfont;
3229 popup_zqdialog_end();
3230 }
3231
3232 /* Grab Tile Code */
3233
3234 enum recolorState { rcNone, rc4Bit, rc8Bit };
3235
3236 BITMAP* original_imagebuf_bitmap=NULL;
3237 void *imagebuf=NULL;
3238 int32_t imagebuf_bitmap_scale=0;
3239 #define IMAGEBUF_SCALE (imagebuf_bitmap_scale > 0 ? imagebuf_bitmap_scale : 1.0 / -imagebuf_bitmap_scale)
3240 int32_t imagesize=0;
3241 int32_t tilecount=0;
3242 int32_t imagetype=0;
3243 int32_t imagex,imagey,selx,sely;
3244 int32_t bp=4,grabmode=16,romofs=0,romtilemode=0, romtilecols=8;
3245 bool nesmode=false;
3246 int32_t grabmask=0;
3247 recolorState recolor=rcNone;
3248 PALETTE imagepal;
3249
3250 /* bestfit_color:
3251 * Searches a palette for the color closest to the requested R, G, B value.
3252 */
3253 int32_t bestfit_cset_color(int32_t cs, int32_t r, int32_t g, int32_t b)
3254 {
3255 int32_t bestMatch = 0; // Color with the lowest total difference so far
3256 float bestTotalDiff = 100000; // Total difference between requested color and bestMatch
3257 float bestHighDiff = 100000; // Greatest difference of R, G, B between requested color and bestMatch
3258
3259 for(int32_t i = 0; i < CSET_SIZE; i++)
3260 {
3261 byte *rgbByte;
3262
3263 // This seems to be right...
3264 if(cs==2 || cs==3 || cs==4)
3265 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + i) * 3;
3266 else if(cs==9)
3267 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + i) * 3;
3268 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3269 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + i) * 3;
3270 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3271 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + i) * 3;
3272 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3273 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + i) * 3;
3274 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3275 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + i) * 3;
3276 else
3277 rgbByte = colordata + (CSET(cs)+i)*3;
3278
3279 int32_t dr=r-*rgbByte;
3280 int32_t dg=g-*(rgbByte+1);
3281 int32_t db=b-*(rgbByte+2);
3282
3283 // Track both the total color difference and the single greatest
3284 // difference of R, G, B. The idea is that it's better to have
3285 // two or three small differences than one big one.
3286 // The differences are multiplied by different numbers to account
3287 // for the differences in perceived brightness of the three colors.
3288 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3289 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3290
3291 // Perfect match? Just stop here.
3292 if(totalDiff==0)
3293 return i;
3294
3295 if(totalDiff < bestTotalDiff || // Best match so far?
3296 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3297 {
3298 bestMatch=i;
3299 bestTotalDiff=totalDiff;
3300 bestHighDiff=highDiff;
3301 }
3302 }
3303
3304 return bestMatch;
3305 }
3306
3307 // Same as the above, but draws from all colors in CSets 0-11.
3308 int32_t bestfit_cset_color_8bit(int32_t r, int32_t g, int32_t b)
3309 {
3310 int32_t bestMatch = 0;
3311 float bestTotalDiff = 100000;
3312 float bestHighDiff = 100000;
3313
3314 for(int32_t i = 0; i < 192; i++) // 192 colors in CSets 0-11
3315 {
3316 byte *rgbByte;
3317
3318 int32_t cs=i>>4;
3319 if(cs==2 || cs==3 || cs==4)
3320 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + (i%16)) * 3;
3321 else if(cs==9)
3322 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + (i%16)) * 3;
3323 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3324 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + (i%16)) * 3;
3325 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3326 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + (i%16)) * 3;
3327 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3328 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + (i%16)) * 3;
3329 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3330 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + (i%16)) * 3;
3331 else
3332 rgbByte = colordata + i * 3;
3333
3334 int32_t dr=r-*rgbByte;
3335 int32_t dg=g-*(rgbByte+1);
3336 int32_t db=b-*(rgbByte+2);
3337
3338 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3339 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3340
3341 if(totalDiff==0) // Perfect match?
3342 return i;
3343
3344 if(totalDiff < bestTotalDiff || // Best match so far?
3345 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3346 {
3347 bestMatch=i;
3348 bestTotalDiff=totalDiff;
3349 bestHighDiff=highDiff;
3350 }
3351 }
3352
3353 return bestMatch;
3354 }
3355
3356 byte cset_reduce_table[PAL_SIZE];
3357
3358 void calc_cset_reduce_table(PALETTE pal, int32_t cs)
3359 {
3360 for(int32_t i=0; i<PAL_SIZE; i++)
3361 {
3362 cset_reduce_table[i]=(bestfit_cset_color(cs, pal[i].r, pal[i].g, pal[i].b)&0x0F);
3363 }
3364 }
3365
3366 void calc_cset_reduce_table_8bit(PALETTE pal)
3367 {
3368 for(int32_t i=0; i<PAL_SIZE; i++)
3369 {
3370 cset_reduce_table[i]=bestfit_cset_color_8bit(pal[i].r, pal[i].g, pal[i].b);
3371 }
3372 }
3373
3374 void puttileROM(BITMAP *dest,int32_t x,int32_t y,byte *src,int32_t cs)
3375 {
3376 //storage space for the grabbed image
3377 byte buf[64];
3378 memset(buf,0,64);
3379 byte *oldsrc=src;
3380
3381 //for 8 lines in the source image...
3382 for(int32_t line=0; line<(nesmode?4:8); line++)
3383 {
3384 //bx is the pixel at the start of a line in the storage buffer
3385 int32_t bx=line<<(nesmode?4:3);
3386 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3387 byte b=src[(bp&1)?line:line<<1];
3388
3389 //fill the storage buffer with data from the source image
3390 for(int32_t i=7; i>=0; --i)
3391 {
3392 buf[bx+i] = (b&1)+(cs<<4);
3393 b>>=1;
3394 }
3395 }
3396
3397 ++src;
3398
3399 for(int32_t p=1; p<bp; p++)
3400 {
3401 for(int32_t line=0; line<(nesmode?4:8); line++)
3402 {
3403 int32_t bx=line<<(nesmode?4:3);
3404 byte b=src[(bp&1)?line:line<<1];
3405
3406 for(int32_t i=7; i>=0; --i)
3407 {
3408 if(nesmode)
3409 {
3410 buf[bx+8+i] = (b&1)+(cs<<4);
3411 }
3412 else
3413 {
3414 buf[bx+i] |= (b&1)<<p;
3415 }
3416
3417 b>>=1;
3418 }
3419 }
3420
3421 if(p&1)
3422 {
3423 src+=15;
3424 }
3425 else
3426 {
3427 ++src;
3428 }
3429 }
3430
3431
3432 if(nesmode)
3433 {
3434 src=oldsrc;
3435
3436 for(int32_t counter=0; counter<2; ++counter, ++src)
3437 {
3438 //for 8 lines in the source image...
3439 for(int32_t line=0; line<4; line++)
3440 {
3441 //bx is the pixel at the start of a line in the storage buffer
3442 int32_t bx=line<<4;
3443 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3444 byte b=src[(line+4)<<1];
3445
3446 //fill the storage buffer with data from the source image
3447 for(int32_t i=7; i>=0; --i)
3448 {
3449 // buf[bx+i] = (b&1)+(cs<<4);
3450 buf[bx+(counter<<3)+i] |= (b&1)<<1;
3451 b>>=1;
3452 }
3453 }
3454 }
3455 }
3456
3457 int32_t c=0;
3458
3459 switch(romtilemode)
3460 {
3461 case 0:
3462 case 1:
3463 case 2:
3464 for(int32_t j=0; j<8; j++)
3465 {
3466 for(int32_t i=0; i<8; i++)
3467 {
3468 putpixel(dest,x+i,y+j,buf[c++]);
3469 }
3470 }
3471
3472 break;
3473
3474 case 3:
3475 for(int32_t j=0; j<4; j++)
3476 {
3477 for(int32_t i=0; i<16; i++)
3478 {
3479 putpixel(dest,x+i,y+j,buf[c++]);
3480 }
3481 }
3482
3483 break;
3484 }
3485 }
3486
3487 const char *file_type[ftMAX]=
3488 {
3489 "None", "BIN", "BMP", "TIL", "ZGP", "QSU", "ZQT", "QST"
3490 };
3491
3492 void draw_grab_window()
3493 {
3494 int w = 640;
3495 int h = 480;
3496 int window_xofs=0;//(zq_screen_w-w-12)>>1;
3497 int window_yofs=0;//(zq_screen_h-h-25-6)>>1;
3498 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
3499 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+2+2-(79*2), FR_DEEP);
3500
3501 FONT *oldfont = font;
3502 font = get_zc_font(font_lfont);
3503 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Grab Tile(s)", true);
3504 font=oldfont;
3505 }
3506
3507 void draw_grab_scr(int32_t tile,int32_t cs,byte *newtile,int32_t black,int32_t white, int32_t width, int32_t height, byte *newformat)
3508 {
3509 width=width;
3510 height=height;
3511 white=white; // happy birthday compiler
3512
3513 int32_t yofs=0;
3514 //clear_to_color(screen2,bg);
3515 rectfill(screen2, 0, 0, 319, 159, black);
3516 rectfill(screen2,0,162,319,239,jwin_pal[jcBOX]);
3517 hline(screen2, 0, 160, 319, jwin_pal[jcMEDLT]);
3518 hline(screen2, 0, 161, 319, jwin_pal[jcLIGHT]);
3519 yofs=3;
3520
3521 // text_mode(-1);
3522 int32_t tileromcolumns=20;
3523
3524 switch(imagetype)
3525 {
3526 case ftBMP:
3527 if(recolor==rcNone)
3528 {
3529 blit((BITMAP*)imagebuf,screen2,imagex<<4,imagey<<4,0,0,320,160);
3530 }
3531 else
3532 {
3533 int32_t maxy=zc_min(160,((BITMAP*)imagebuf)->h);
3534 int32_t maxx=zc_min(320,((BITMAP*)imagebuf)->w);
3535
3536 for(int32_t y=0; y<maxy; y++)
3537 {
3538 if((imagey<<4)+y>=((BITMAP*)imagebuf)->h)
3539 {
3540 break;
3541 }
3542
3543 for(int32_t x=0; x<maxx; x++)
3544 {
3545 if((imagex<<4)+x>=((BITMAP*)imagebuf)->w)
3546 {
3547 break;
3548 }
3549
3550 if(recolor==rc8Bit)
3551 screen2->line[y][x]=cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]];
3552 else
3553 screen2->line[y][x]=(cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]])+(cs<<4);
3554 }
3555 }
3556 }
3557
3558 break;
3559
3560 case ftZGP:
3561 case ftQST:
3562 case ftZQT:
3563 case ftQSU:
3564 case ftTIL:
3565 {
3566 tiledata *hold = newtilebuf;
3567 newtilebuf = grabtilebuf;
3568 //fixme
3569 imagey = vbound(imagey, 0, MAXTILEROWS); //fixed -Z This can no longer crash if you scroll past the end of the tile pages. 6th June, 2020
3570 int32_t t=imagey*TILES_PER_ROW;
3571
3572 for(int32_t i=0; i<200; i++) // 10 rows, down to y=160
3573 {
3574 if(t <= tilecount)
3575 {
3576 puttile16(screen2,t,(i%TILES_PER_ROW)<<4,(i/TILES_PER_ROW)<<4,cs,0);
3577 }
3578
3579 ++t;
3580 }
3581
3582 newtilebuf = hold;
3583 //fixme
3584 }
3585 break;
3586
3587 case ftBIN:
3588 {
3589 int32_t ofs = (tileromcolumns*imagex + imagey) * 128*bp + romofs;
3590 byte *buf = (byte*)imagebuf;
3591
3592 switch(romtilemode)
3593 {
3594 case 0:
3595 for(int32_t y=0; y<160; y+=8)
3596 {
3597 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3598 {
3599 puttileROM(screen2,x,y,buf+ofs,cs);
3600 ofs+=8*bp;
3601 }
3602 }
3603
3604 for(int32_t y=0; y<160; y+=8)
3605 {
3606 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3607 {
3608 puttileROM(screen2,x+128,y,buf+ofs,cs);
3609 ofs+=8*bp;
3610 }
3611 }
3612
3613 break;
3614
3615 case 1:
3616 for(int32_t y=0; y<160; y+=16)
3617 {
3618 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3619 {
3620 puttileROM(screen2,x,y,buf+ofs,cs);
3621 ofs+=8*bp;
3622 puttileROM(screen2,x,y+8,buf+ofs,cs);
3623 ofs+=8*bp;
3624 }
3625 }
3626
3627 for(int32_t y=0; y<160; y+=16)
3628 {
3629 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3630 {
3631 puttileROM(screen2,x+128,y,buf+ofs,cs);
3632 ofs+=8*bp;
3633 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3634 ofs+=8*bp;
3635 }
3636 }
3637
3638 break;
3639
3640 case 2:
3641 for(int32_t y=0; y<160; y+=16)
3642 {
3643 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3644 {
3645 puttileROM(screen2,x,y,buf+ofs,cs);
3646 ofs+=8*bp;
3647 puttileROM(screen2,x+8,y,buf+ofs,cs);
3648 ofs+=8*bp;
3649 puttileROM(screen2,x,y+8,buf+ofs,cs);
3650 ofs+=8*bp;
3651 puttileROM(screen2,x+8,y+8,buf+ofs,cs);
3652 ofs+=8*bp;
3653 }
3654 }
3655
3656 for(int32_t y=0; y<160; y+=16)
3657 {
3658 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3659 {
3660 puttileROM(screen2,x+128,y,buf+ofs,cs);
3661 ofs+=8*bp;
3662 puttileROM(screen2,x+136,y,buf+ofs,cs);
3663 ofs+=8*bp;
3664 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3665 ofs+=8*bp;
3666 puttileROM(screen2,x+136,y+8,buf+ofs,cs);
3667 ofs+=8*bp;
3668 }
3669 }
3670
3671 break;
3672
3673 case 3:
3674 for(int32_t y=0; y<160; y+=16)
3675 {
3676 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3677 {
3678 puttileROM(screen2,x,y,buf+ofs,cs);
3679 ofs+=8*bp;
3680 puttileROM(screen2,x,y+4,buf+ofs,cs);
3681 ofs+=8*bp;
3682 puttileROM(screen2,x,y+8,buf+ofs,cs);
3683 ofs+=8*bp;
3684 puttileROM(screen2,x,y+12,buf+ofs,cs);
3685 ofs+=8*bp;
3686 }
3687 }
3688
3689 for(int32_t y=0; y<160; y+=16)
3690 {
3691 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3692 {
3693 puttileROM(screen2,x+128,y,buf+ofs,cs);
3694 ofs+=8*bp;
3695 puttileROM(screen2,x+128,y+4,buf+ofs,cs);
3696 ofs+=8*bp;
3697 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3698 ofs+=8*bp;
3699 puttileROM(screen2,x+128,y+12,buf+ofs,cs);
3700 ofs+=8*bp;
3701 }
3702 }
3703
3704 break;
3705 }
3706 }
3707 break;
3708 }
3709
3710 tiledata hold;
3711 bool holdblank = blank_tile_table[0];
3712
3713 if(is_valid_format(newtilebuf[0].format))
3714 {
3715 hold.format = newtilebuf[0].format;
3716 hold.data = (byte *)malloc(tilesize(hold.format));
3717 memcpy(hold.data, newtilebuf[0].data, tilesize(hold.format));
3718 }
3719 else
3720 {
3721 hold.format=tfInvalid;
3722 hold.data=NULL;
3723 }
3724
3725 newtilebuf[0].format=newformat[0];
3726 blank_tile_table[0] = false;
3727
3728 if(newtilebuf[0].data!=NULL)
3729 {
3730 free(newtilebuf[0].data);
3731 }
3732
3733 if(is_valid_format(newtilebuf[0].format))
3734 {
3735 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3736
3737 for(int32_t i=0; i<tilesize(newtilebuf[0].format); i++)
3738 {
3739 newtilebuf[0].data[i]=newtile[i];
3740 }
3741 }
3742 else
3743 {
3744 newtilebuf[0].data=NULL;
3745 }
3746
3747 puttile16(screen2,0,208,168+yofs,cs,0);
3748 overtile16(screen2,0,232,168+yofs,cs,0);
3749 newtilebuf[0].format=hold.format;
3750 blank_tile_table[0] = holdblank;
3751
3752 if(newtilebuf[0].data!=NULL)
3753 {
3754 free(newtilebuf[0].data);
3755 }
3756
3757 if(is_valid_format(newtilebuf[0].format))
3758 {
3759 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3760
3761 for(int32_t i=0; i<256; i++)
3762 {
3763 newtilebuf[0].data[i]=hold.data[i];
3764 }
3765 }
3766 else
3767 {
3768 newtilebuf[0].data=NULL;
3769 }
3770
3771 if(hold.data!=NULL)
3772 {
3773 free(hold.data);
3774 }
3775
3776 puttile16(screen2,tile,208,192+yofs,cs,0);
3777 overtile16(screen2,tile,232,192+yofs,cs,0);
3778
3779 rectfill(screen2,184,168+yofs,191,175+yofs,grabmask&1?vc(12):vc(7));
3780 rectfill(screen2,192,168+yofs,199,175+yofs,grabmask&2?vc(12):vc(7));
3781 rectfill(screen2,184,176+yofs,191,183+yofs,grabmask&4?vc(12):vc(7));
3782 rectfill(screen2,192,176+yofs,199,183+yofs,grabmask&8?vc(12):vc(7));
3783
3784 // rect(screen2,183,167,200,184,dvc(7*2));
3785 // rect(screen2,207,167,224,184,dvc(7*2));
3786 // rect(screen2,231,167,248,184,dvc(7*2));
3787 // rect(screen2,207,191,224,208,dvc(7*2));
3788 // rect(screen2,231,191,248,208,dvc(7*2));
3789
3790 /*
3791 rect(screen2,183,167,200,184,vc(14));
3792 rect(screen2,207,167,224,184,vc(14));
3793 rect(screen2,231,167,248,184,vc(14));
3794 rect(screen2,207,191,224,208,vc(14));
3795 rect(screen2,231,191,248,208,vc(14));
3796 */
3797 jwin_draw_frame(screen2,182,166+yofs,20,20,FR_DEEP);
3798 jwin_draw_frame(screen2,206,166+yofs,20,20,FR_DEEP);
3799 jwin_draw_frame(screen2,230,166+yofs,20,20,FR_DEEP);
3800 jwin_draw_frame(screen2,206,190+yofs,20,20,FR_DEEP);
3801 jwin_draw_frame(screen2,230,190+yofs,20,20,FR_DEEP);
3802 int32_t screen_xofs=6;
3803 int32_t screen_yofs=25;
3804 int winh = 511;
3805 int32_t mul = 2;
3806
3807 yofs=16;
3808
3809 custom_vsync();
3810
3811 stretch_blit(screen2,screen,0,0,320,240,screen_xofs,screen_yofs,640,480);
3812
3813 // Suspend the current font while draw_text_button does its work
3814 FONT* oldfont = font;
3815
3816 font = get_zc_font(font_lfont_l);
3817
3818 int txt_x = 8*mul;
3819 int rbtn_x = 255*mul;
3820 int max_fpath_wid = rbtn_x-2-txt_x;
3821 int max_fpath_wid2 = max_fpath_wid-text_length(font,"... ");
3822 // Interface
3823 switch(imagetype)
3824 {
3825 case 0:
3826 textprintf_ex(screen,font,txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s",imgstr[imagetype]);
3827 break;
3828
3829 case ftBMP:
3830 {
3831 std::string text = fmt::format("{} {}x{}, {:.2g}x zoom with , and .", imgstr[imagetype], original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, IMAGEBUF_SCALE);
3832 int text_x = txt_x;
3833 int text_y = (216 + yofs) * mul;
3834 // TODO: can almost use this, but drawing is offset. prob cuz drawing to a different bitmap than the normal screen bitmap? idk
3835 // int text_w = text_length(font, text.c_str());
3836 // int text_h = text_height(font);
3837 // static int grab_scale_tooltip_id = ttip_register_id();
3838 // ttip_install(grab_scale_tooltip_id, "zoom with , and .", text_x, text_y, text_w, text_h, text_x, text_y - 40);
3839 textprintf_ex(screen, font, text_x, text_y, jwin_pal[jcTEXTFG], jwin_pal[jcBOX], "%s", text.c_str());
3840
3841 draw_text_button(screen,117*mul,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Recolor",vc(1),vc(14),0,true);
3842 break;
3843 }
3844
3845 case ftZGP:
3846 case ftQST:
3847 case ftZQT:
3848 case ftQSU:
3849 case ftTIL:
3850 case ftBIN:
3851 textprintf_ex(screen,get_zc_font(font_lfont_l),txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s %d KB",imgstr[imagetype],imagesize>>10);
3852 break;
3853 }
3854
3855 textprintf_ex(screen,font,txt_x,(168+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"sel: %d %d",selx,sely);
3856 textprintf_ex(screen,font,txt_x,(176+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"pos: %d %d",imagex,imagey);
3857
3858 if(bp==8)
3859 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"8-bit");
3860 else
3861 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"cset: %d",cs);
3862 textprintf_ex(screen,font,txt_x,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"step: %d",grabmode);
3863
3864 if(imagetype==ftBIN)
3865 {
3866 textprintf_ex(screen,font,104*mul,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"bp: %d%s",bp,nesmode?" (NES)":"");
3867 textprintf_ex(screen,font,104*mul,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"ofs: %Xh",romofs);
3868 textprintf_ex(screen,font,104*mul,(208+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"m: %d",romtilemode);
3869 }
3870
3871 int fpath_y = (224+yofs)*mul;
3872 if(text_length(font,imagepath) <= max_fpath_wid)
3873 textout_ex(screen,font,imagepath,txt_x,fpath_y,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3874 else
3875 {
3876 char buf[2052] = {0};
3877 strncpy(buf,imagepath,2048);
3878 int len = strlen(buf);
3879 char *ptr = buf;
3880 char *endptr = buf+len;
3881 char *it = endptr;
3882 int tmpy = fpath_y;
3883 int tmph = text_height(font)+1;
3884 while(true)
3885 {
3886 if(tmpy+tmph > (winh-2))
3887 break; //Out of space!
3888 char c = *it;
3889 bool end = !c;
3890 *it = 0;
3891 int newlen = text_length(font,ptr);
3892 if(newlen <= (end ? max_fpath_wid : max_fpath_wid2))
3893 {
3894 if(end) //No stored character, string ended
3895 {
3896 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3897 break;
3898 }
3899 char t[5];
3900 t[0] = c;
3901 for(int q = 1; q < 5; ++q)
3902 t[q] = it[q];
3903 strcpy(it,"...");
3904 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3905 for(int q = 0; q < 5; ++q)
3906 it[q] = t[q];
3907 tmpy += tmph;
3908 ptr = it;
3909 it = endptr;
3910 }
3911 else
3912 {
3913 *it = c;
3914 --it;
3915 }
3916 }
3917 }
3918 draw_text_button(screen,rbtn_x,(168+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"OK",vc(1),vc(14),0,true);
3919 draw_text_button(screen,rbtn_x,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Cancel",vc(1),vc(14),0,true);
3920 draw_text_button(screen,rbtn_x,(216+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"File",vc(1),vc(14),0,true);
3921 draw_text_button(screen,117*mul,(166+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Leech",vc(1),vc(14),0,true);
3922
3923 //int32_t rectw = 16*mul;
3924 //rect(screen,selx+screen_xofs,sely+screen_yofs,selx+screen_xofs+((width-1)*rectw)+rectw-1,sely+screen_yofs+((height-1)*rectw)+rectw-1,white);
3925 SCRFIX();
3926 font = oldfont;
3927 }
3928
3929 RGB_MAP rgb_table;
3930 COLOR_MAP imagepal_table;
3931
3932
3933 extern void return_RAMpal_color(AL_CONST PALETTE pal, int32_t x, int32_t y, RGB *rgb)
3934 {
3935 //these are here to bypass compiler warnings about unused arguments
3936 x=x;
3937
3938 rgb->r = pal[y].r;
3939 rgb->g = pal[y].g;
3940 rgb->b = pal[y].b;
3941 }
3942
3943
3944 void load_imagebuf()
3945 {
3946 PACKFILE *f;
3947 //cache QRS
3948 //byte cached_rules[QUESTRULES_NEW_SIZE] = { 0 };
3949 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
3950 // {
3951 // cached_rules[q] = quest_rules[q];
3952 // }
3953 bool compressed=false;
3954 bool encrypted=false;
3955 tiledata *hold=newtilebuf;
3956 zquestheader tempheader;
3957 memset(&tempheader, 0, sizeof(zquestheader));
3958
3959 if(imagebuf)
3960 {
3961 switch(imagetype)
3962 {
3963 case ftBMP:
3964 if (original_imagebuf_bitmap != imagebuf)
3965 destroy_bitmap((BITMAP*)imagebuf);
3966 destroy_bitmap(original_imagebuf_bitmap);
3967 break;
3968
3969 case ftZGP:
3970 case ftQST:
3971 case ftZQT:
3972 case ftQSU:
3973 case ftTIL:
3974 clear_tiles(grabtilebuf);
3975 break;
3976
3977 case ftBIN:
3978 free(imagebuf);
3979 break;
3980 }
3981
3982 imagebuf=NULL;
3983 original_imagebuf_bitmap=NULL;
3984 }
3985
3986 selx=sely=romofs=0;
3987 bp=4;
3988 imagetype=filetype(imagepath);
3989
3990 dword section_id;
3991 dword section_version;
3992 dword section_cversion;
3993
3994 switch(imagetype)
3995 {
3996 case ftBMP:
3997 packfile_password("");
3998 memset(imagepal, 0, sizeof(PALETTE));
3999 original_imagebuf_bitmap = load_bitmap(imagepath,imagepal);
4000 imagesize = file_size_ex_password(imagepath,"");
4001 tilecount=0;
4002 create_rgb_table(&rgb_table, imagepal, NULL);
4003 rgb_map = &rgb_table;
4004 create_color_table(&imagepal_table, RAMpal, return_RAMpal_color, NULL);
4005
4006 if(!original_imagebuf_bitmap)
4007 {
4008 imagetype=0;
4009 }
4010 else
4011 {
4012 imagebuf = original_imagebuf_bitmap;
4013 imagebuf_bitmap_scale = 1;
4014 }
4015
4016 break;
4017
4018 case ftBIN:
4019 packfile_password("");
4020 imagesize = file_size_ex_password(imagepath, "");
4021 tilecount=0;
4022
4023 if(imagesize)
4024 {
4025 imagebuf = malloc(imagesize);
4026
4027 if(!readfile(imagepath,imagebuf,imagesize))
4028 {
4029 free(imagebuf);
4030 imagesize=0;
4031 imagetype=0;
4032 }
4033 }
4034
4035 break;
4036
4037 case ftTIL:
4038 packfile_password("");
4039 imagesize = file_size_ex_password(imagepath,"");
4040 f = pack_fopen_password(imagepath,F_READ,"");
4041
4042 if(!f)
4043 {
4044 goto error;
4045 }
4046
4047 if(!p_mgetl(&section_id,f))
4048 {
4049 goto error;
4050 }
4051
4052 if(section_id==ID_TILES)
4053 {
4054 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)==0)
4055 {
4056 goto error;
4057 }
4058 }
4059
4060 error:
4061 pack_fclose(f);
4062 tilecount=count_tiles(grabtilebuf);
4063 break;
4064
4065 case ftZGP:
4066 packfile_password("");
4067 imagesize = file_size_ex_password(imagepath, "");
4068 f=pack_fopen_password(imagepath,F_READ,"");
4069
4070 if(!f)
4071 {
4072 goto error2;
4073 }
4074
4075 if(!p_mgetl(&section_id,f))
4076 {
4077 goto error2;
4078 }
4079
4080 if(section_id!=ID_GRAPHICSPACK)
4081 {
4082 goto error2;
4083 }
4084
4085 //section version info
4086 if(!p_igetw(&section_version,f))
4087 {
4088 goto error2;
4089 }
4090
4091 if(!p_igetw(&section_cversion,f))
4092 {
4093 goto error2;
4094 }
4095
4096 //tiles
4097 if(!p_mgetl(&section_id,f))
4098 {
4099 goto error2;
4100 }
4101
4102 if(section_id==ID_TILES)
4103 {
4104 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)!=0)
4105 {
4106 goto error2;
4107 }
4108 }
4109
4110 error2:
4111 pack_fclose(f);
4112 tilecount=count_tiles(grabtilebuf);
4113 break;
4114
4115 case ftQST:
4116 encrypted=true;
4117 case ftZQT:
4118 compressed=true;
4119 case ftQSU:
4120 packfile_password("");
4121 imagesize = file_size_ex_password(imagepath, encrypted ? datapwd : "");
4122 newtilebuf=grabtilebuf;
4123 byte skip_flags[4];
4124
4125 for(int32_t i=0; i<skip_max; ++i)
4126 {
4127 set_bit(skip_flags,i,1);
4128 }
4129
4130 set_bit(skip_flags,skip_tiles,0);
4131 set_bit(skip_flags,skip_header,0);
4132 int ret = loadquest(imagepath,&tempheader,&QMisc,customtunes,true,skip_flags);
4133 if (ret)
4134 {
4135 imagetype=0;
4136 imagesize=0;
4137 clear_tiles(grabtilebuf);
4138 chop_path(imagepath);
4139 }
4140
4141 if (!ret && encrypted && compressed)
4142 {
4143 if(quest_access(imagepath, &tempheader) != 1)
4144 {
4145 imagetype=0;
4146 imagesize=0;
4147 clear_tiles(grabtilebuf);
4148 chop_path(imagepath);
4149 }
4150 }
4151
4152 //setPackfilePassword(NULL);
4153 newtilebuf=hold;
4154 tilecount=count_tiles(grabtilebuf);
4155 break;
4156 }
4157
4158 rgb_map = &zq_rgb_table;
4159 //restore cashed QRs / rules
4160
4161 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
4162 // {
4163 // quest_rules[q] = cached_rules[q];
4164 // }
4165 }
4166
4167 static char bitstrbuf[32];
4168 bool leeching_from_tiles=false;
4169
4170 const char *bitlist(int32_t index, int32_t *list_size)
4171 {
4172 int32_t imported=2;
4173
4174 if(index>=0)
4175 {
4176 bound(index,0,leeching_from_tiles?2:1);
4177
4178 if(index==imported)
4179 {
4180 sprintf(bitstrbuf,"Imported");
4181 }
4182 else
4183 {
4184 sprintf(bitstrbuf,"%d",4<<index);
4185 }
4186
4187 return bitstrbuf;
4188 }
4189
4190 *list_size=leeching_from_tiles?3:2;
4191 return NULL;
4192 }
4193
4194 9 static ListData bit_list(bitlist, &font);
4195
4196 static DIALOG leech_dlg[] =
4197 {
4198 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
4199 9 { jwin_win_proc, 8, 20-4, 303+1, 216-42+1, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Leech Options", NULL, NULL },
4200 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
4201 // 2
4202 9 { jwin_button_proc, 180, 210-42-4, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
4203 9 { jwin_button_proc, 80, 210-42-4, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
4204 9 { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL },
4205 // 5
4206 9 { jwin_text_proc, 14, 49-4, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Update Status Every: ", NULL, NULL },
4207 9 { jwin_edit_proc, 114, 45-4, 36, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL },
4208 9 { jwin_radio_proc, 155, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Tiles", NULL, NULL },
4209 9 { jwin_radio_proc, 200, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Seconds", NULL, NULL },
4210 //9
4211 9 { jwin_frame_proc, 14, 63-2, 176+70, 50+30, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL },
4212 9 { jwin_text_proc, 14+8, 60-2, 80, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) " Duplicates ", NULL, NULL },
4213
4214 9 { jwin_check_proc, 20, 70, 168, 8+1, vc(15), vc(1), 0, 0, 1, 0, (void *) "Only check new tiles", NULL, NULL },
4215 9 { jwin_text_proc, 20, 90, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Normal:", NULL, NULL },
4216 9 { jwin_text_proc, 20, 100, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal Flip:", NULL, NULL },
4217 9 { jwin_text_proc, 20, 110, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Vertical Flip:", NULL, NULL },
4218 9 { jwin_text_proc, 20, 120, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal/Vertical Flip:", NULL, NULL },
4219 //16
4220 9 { jwin_radio_proc, 144, 90, 64+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4221 9 { jwin_radio_proc, 184, 90, 56+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4222 9 { jwin_radio_proc, 224, 90, 72+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4223
4224 9 { jwin_radio_proc, 144, 100, 64+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4225 9 { jwin_radio_proc, 184, 100, 56+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4226 9 { jwin_radio_proc, 224, 100, 72+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4227
4228 9 { jwin_radio_proc, 144, 110, 64+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4229 9 { jwin_radio_proc, 184, 110, 56+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4230 9 { jwin_radio_proc, 224, 110, 72+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4231
4232 9 { jwin_radio_proc, 144, 120, 64+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4233 9 { jwin_radio_proc, 184, 120, 56+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4234 9 { jwin_radio_proc, 224, 120, 72+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4235
4236 9 { jwin_ctext_proc, 144+4, 80, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Ignore", NULL, NULL },
4237 9 { jwin_ctext_proc, 184+4, 80, 56+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Check", NULL, NULL },
4238 9 { jwin_ctext_proc, 224+4, 80, 72+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Discard", NULL, NULL },
4239 9 { jwin_droplist_proc, 76, 145, 80, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &bit_list, NULL, NULL },
4240 9 { jwin_text_proc, 14, 149, 60, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Color Depth: ", NULL, NULL },
4241 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
4242 };
4243
4244 bool leech_tiles(tiledata *dest,int32_t start,int32_t cs)
4245 {
4246 bool shift=true; // fix this!
4247 int32_t cst=0;
4248 int32_t currtile=start;
4249 int32_t height=0, width=0;
4250 byte *testtile = new byte[tilesize(tf32Bit)];
4251 byte imported_format=0;
4252 char updatestring[6];
4253 bool canadd;
4254 bool temp_canadd;
4255 bool duplicate;
4256 int32_t total_duplicates_found=0, total_duplicates_discarded=0;
4257 int32_t duplicates_found[4]= //, duplicates_discarded[4]={0,0,0,0};
4258 {
4259 0,0,0,0
4260 };
4261 BITMAP *status;
4262 status = create_bitmap_ex(8,240,140);
4263 clear_bitmap(status);
4264 sprintf(updatestring, "%d", LeechUpdate);
4265 leech_dlg[0].dp2=get_zc_font(font_lfont);
4266 leech_dlg[6].dp=updatestring;
4267
4268 leech_dlg[10].flags=(OnlyCheckNewTilesForDuplicates!=0) ? D_SELECTED : 0;
4269
4270 for(int32_t i=0; i<2; i++)
4271 {
4272 leech_dlg[i+7].flags=0;
4273 }
4274
4275 leech_dlg[7+((LeechUpdateTiles==0) ? 1 : 0)].flags=D_SELECTED;
4276
4277 for(int32_t i=0; i<12; i++)
4278 {
4279 leech_dlg[i+16].flags=0;
4280 }
4281
4282 for(int32_t i=0; i<4; i++)
4283 {
4284 leech_dlg[(DuplicateAction[i])+16+(i*3)].flags=D_SELECTED;
4285 }
4286
4287 leech_dlg[31].d1=0;
4288
4289 large_dialog(leech_dlg);
4290
4291 int32_t ret = do_zqdialog(leech_dlg,3);
4292
4293 if(ret==2)
4294 {
4295 delete[] testtile;
4296 return false;
4297 }
4298
4299 int32_t cdepth=leech_dlg[31].d1+1;
4300 int32_t newformat=0;
4301 auto lu = atoi(updatestring);
4302 auto lut = (leech_dlg[7].flags&D_SELECTED)?1:0;
4303 if(LeechUpdate!=lu)
4304 {
4305 LeechUpdate=lu;
4306 zc_set_config("zquest","leech_update",LeechUpdate);
4307 }
4308 if(LeechUpdateTiles!=lut)
4309 {
4310 LeechUpdateTiles=lut;
4311 zc_set_config("zquest","leech_update_tiles",LeechUpdateTiles);
4312 }
4313
4314 int32_t old_dupe[4];
4315 for(int32_t j=0; j<4; j++)
4316 {
4317 old_dupe[j] = DuplicateAction[j];
4318 for(int32_t i=0; i<3; i++)
4319 {
4320 if(leech_dlg[i+16+(j*3)].flags&D_SELECTED)
4321 {
4322 DuplicateAction[j]=i;
4323 }
4324 }
4325 }
4326 if(old_dupe[0] != DuplicateAction[0])
4327 zc_set_config("zquest","normal_duplicate_action",DuplicateAction[0]);
4328 if(old_dupe[1] != DuplicateAction[1])
4329 zc_set_config("zquest","horizontal_duplicate_action",DuplicateAction[1]);
4330 if(old_dupe[2] != DuplicateAction[2])
4331 zc_set_config("zquest","vertical_duplicate_action",DuplicateAction[2]);
4332 if(old_dupe[3] != DuplicateAction[3])
4333 zc_set_config("zquest","both_duplicate_action",DuplicateAction[3]);
4334
4335 auto ocntfd = leech_dlg[10].flags&D_SELECTED?1:0;
4336 if(OnlyCheckNewTilesForDuplicates!=ocntfd)
4337 {
4338 OnlyCheckNewTilesForDuplicates=ocntfd;
4339 zc_set_config("zquest","only_check_new_tiles_for_duplicates",ocntfd);
4340 }
4341
4342 leeching_from_tiles=false;
4343
4344 switch(imagetype)
4345 {
4346 case ftBIN:
4347 width=imagesize/128;
4348 height=1;
4349 break;
4350
4351 case ftZGP:
4352 case ftQST:
4353 case ftZQT:
4354 case ftQSU:
4355 case ftTIL:
4356 leeching_from_tiles=true;
4357 width=count_tiles(grabtilebuf);
4358 height=1;
4359 break;
4360
4361 case ftBMP:
4362 width=((((BITMAP*)imagebuf)->w)+15)/16;
4363 height=((((BITMAP*)imagebuf)->h)+15)/16;
4364 break;
4365 }
4366
4367 if(currtile+(width*height)>NEWMAXTILES)
4368 {
4369 if(jwin_alert("Confirm Truncation","Too many tiles.","Truncation may occur.",NULL,"&OK","&Cancel",'o','c',get_zc_font(font_lfont))==2)
4370 {
4371 delete[] testtile;
4372 return false;
4373 }
4374 }
4375
4376 go_tiles();
4377 saved=false;
4378
4379 for(int32_t ty=0; ty<height; ty++) //for every row
4380 {
4381 for(int32_t tx=0; tx<width; tx++) //for every column (tile)
4382 {
4383 if((((ty*width)+tx)%zc_max(LeechUpdate, 1))==0) //update status
4384 {
4385 FONT *oldfont = font;
4386 static BITMAP *tbar = create_bitmap_ex(8,240-6, 18);
4387 static bool created_tbar=false;
4388 jwin_draw_win(status, 0, 0, 240, 140, FR_WIN);
4389
4390 if(created_tbar)
4391 {
4392 blit(tbar, status, 0, 0, 3, 3, 240-6, 18);
4393 }
4394 else
4395 {
4396 font = get_zc_font(font_lfont);
4397 jwin_draw_titlebar(tbar, 0, 0, 240-6, 18, "Leech Status", false);
4398 font = oldfont;
4399 created_tbar=true;
4400 blit(tbar, status, 0, 0, 3, 3, 320-6, 18);
4401 }
4402
4403 textprintf_centre_ex(status,font,120,24,jwin_pal[jcTEXTFG],-1,"Checking %d of %d",((ty*width)+tx), (width*height));
4404 textprintf_centre_ex(status,font,120,34,jwin_pal[jcTEXTFG],-1,"%d tiles imported",currtile-start);
4405 jwin_draw_frame(status, 40, 49, 160, 70, FR_ETCHED);
4406 textprintf_centre_ex(status,font,120,46,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]," Duplicates ");
4407 textprintf_centre_ex(status,font,120,56,jwin_pal[jcTEXTFG],-1,"%d/%d found/discarded",total_duplicates_found, total_duplicates_discarded);
4408 textprintf_centre_ex(status,font,120,76,jwin_pal[jcTEXTFG],-1,"%d normal %s",duplicates_found[0],((DuplicateAction[0]<2)?"found":"discarded"));
4409 textprintf_centre_ex(status,font,120,86,jwin_pal[jcTEXTFG],-1,"%d flipped (h) %s",duplicates_found[1],((DuplicateAction[1]<2)?"found":"discarded"));
4410 textprintf_centre_ex(status,font,120,96,jwin_pal[jcTEXTFG],-1,"%d flipped (v) %s",duplicates_found[2],((DuplicateAction[2]<2)?"found":"discarded"));
4411 textprintf_centre_ex(status,font,120,106,jwin_pal[jcTEXTFG],-1,"%d flipped (hv) %s",duplicates_found[3],((DuplicateAction[3]<2)?"found":"discarded"));
4412 textprintf_centre_ex(status,font,120,128,jwin_pal[jcTEXTFG],-1,"Press any key to stop.");
4413 blit(status,screen,0, 0, 40, 20, 240, 140);
4414 SCRFIX();
4415 }
4416
4417 canadd=true;
4418
4419 if(currtile>=NEWMAXTILES) //if we've maxed out on our tiles...
4420 {
4421 delete[] testtile;
4422 return true;
4423 }
4424
4425 switch(imagetype)
4426 {
4427 case ftBIN:
4428 break;
4429
4430 case ftZGP:
4431 case ftQST:
4432 case ftZQT:
4433 case ftQSU:
4434 case ftTIL:
4435 memset(testtile, 0, tilesize(tf32Bit));
4436 imported_format=grabtilebuf[tx].format;
4437
4438 switch(cdepth)
4439 {
4440 case 1: //4-bit
4441 newformat=tf4Bit;
4442
4443 switch(imported_format)
4444 {
4445 case tf4Bit:
4446 case tf8Bit:
4447 for(int32_t y=0; y<16; y++) //snag a tile
4448 {
4449 for(int32_t x=0; x<16; x+=2)
4450 {
4451 testtile[(y*8)+(x/2)]=
4452 (grabtilebuf[tx].data[y*16+x]&15)+
4453 ((grabtilebuf[tx].data[y*16+x+1]&15)<<4);
4454 }
4455 }
4456
4457 break;
4458 }
4459
4460 break;
4461
4462 case 2: //8-bit
4463 newformat=tf8Bit;
4464
4465 switch(imported_format)
4466 {
4467 case tf4Bit:
4468 unpack_tile(grabtilebuf, tx, 0, true);
4469 cst = cs&15;
4470 cst <<= CSET_SHFT;
4471
4472 for(int32_t i=0; i<256; i++)
4473 {
4474 if(!shift||unpackbuf[i]!=0)
4475 {
4476 unpackbuf[i]+=cst;
4477 }
4478 }
4479
4480 pack_tiledata(testtile, unpackbuf, tf8Bit);
4481 break;
4482
4483 case tf8Bit:
4484 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4485 break;
4486 }
4487
4488 break;
4489
4490 case 3: //original tile's bit depth
4491 newformat=imported_format;
4492 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4493 break;
4494 }
4495
4496 break;
4497
4498 case ftBMP:
4499 newformat=cdepth;
4500
4501 for(int32_t y=0; y<16; y++) //snag a tile
4502 {
4503 for(int32_t x=0; x<16; x+=2)
4504 {
4505 testtile[(y*16)+x]=getpixel(((BITMAP*)imagebuf),(tx*16)+x,(ty*16)+y);
4506 testtile[(y*16)+x+1]=getpixel(((BITMAP*)imagebuf),(tx*16)+x+1,(ty*16)+y);
4507 }
4508 }
4509
4510 break;
4511 }
4512
4513 if(DuplicateAction[0]+DuplicateAction[1]+DuplicateAction[2]+DuplicateAction[3]>0)
4514 {
4515 temp_canadd=true;
4516
4517 //check all tiles before this one
4518 for(int32_t checktile=((OnlyCheckNewTilesForDuplicates!=0)?start:0); ((temp_canadd==true)&&(checktile<currtile)); checktile++)
4519 {
4520 for(int32_t flipping=0; ((temp_canadd==true)&&(flipping<4)); ++flipping)
4521 {
4522 if(DuplicateAction[flipping]>0)
4523 {
4524 if(keypressed())
4525 {
4526 delete[] testtile;
4527 return true;
4528 }
4529
4530 duplicate=(newformat==imported_format);
4531
4532 if(duplicate)
4533 {
4534 switch(flipping)
4535 {
4536 case 0: //normal
4537 if(dest[checktile].data!=NULL)
4538 {
4539 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4540 {
4541 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4542 {
4543 // if ((dest[(checktile*128)+(y*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4544 if((dest[checktile].data[(y*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4545 {
4546 duplicate=false;
4547 }
4548 }
4549 }
4550 }
4551
4552 break;
4553
4554 case 1: //horizontal
4555 if(dest[checktile].data!=NULL)
4556 {
4557 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4558 {
4559 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4560 {
4561 // if ((dest[(checktile*128)+(y*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4562 if((dest[checktile].data[(y*8*newformat)+(14+(newformat-1)-x)/(3-newformat)])!=testtile[(y*16)+x])
4563 {
4564 duplicate=false;
4565 }
4566 }
4567 }
4568 }
4569
4570 break;
4571
4572 case 2: //vertical
4573 if(dest[checktile].data!=NULL)
4574 {
4575 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4576 {
4577 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4578 {
4579 // if ((dest[(checktile*128)+((15-y)*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4580 if((dest[checktile].data[((15-y)*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4581 {
4582 duplicate=false;
4583 }
4584 }
4585 }
4586 }
4587
4588 break;
4589
4590 case 3: //both
4591 if(dest[checktile].data!=NULL)
4592 {
4593 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4594 {
4595 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4596 {
4597 // if ((dest[(checktile*128)+((15-y)*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4598 if((dest[checktile].data[((15-y)*8*newformat)+((14+(newformat-1)-x)/(3-newformat))])!=testtile[(y*16)+x])
4599 {
4600 duplicate=false;
4601 }
4602 }
4603 }
4604 }
4605
4606 break;
4607 }
4608 }
4609
4610 if(duplicate==true)
4611 {
4612 ++duplicates_found[flipping];
4613 ++total_duplicates_found;
4614
4615 if(DuplicateAction[flipping]>1)
4616 {
4617 ++total_duplicates_discarded;
4618 temp_canadd=false;
4619 }
4620 }
4621 }
4622
4623 canadd=canadd&&temp_canadd;
4624 }
4625 }
4626 }
4627
4628 // dest[currtile].format=(cdepth==3?imported_format:cdepth);
4629 dest[currtile].format=newformat;
4630
4631 if(dest[currtile].data!=NULL)
4632 {
4633 free(dest[currtile].data);
4634 }
4635
4636 dest[currtile].data=(byte *)malloc(tilesize(dest[currtile].format));
4637
4638 if(dest[currtile].data==NULL)
4639 {
4640 Z_error_fatal("Unable to initialize tile #%d.\n", currtile);
4641 }
4642
4643 if(canadd==true)
4644 {
4645 /*
4646 for(int32_t y=0; y<16; y++)
4647 {
4648 for(int32_t x=0; x<8; x++)
4649 {
4650 dest[currtile].data[(y*8)+x]=testtile[(y*8)+x];
4651 }
4652 }
4653 */
4654 memcpy(dest[currtile].data, testtile, tilesize(dest[currtile].format));
4655 ++currtile;
4656 }
4657 }
4658 }
4659
4660 destroy_bitmap(status);
4661 delete[] testtile;
4662 return true;
4663 }
4664
4665 void grab(byte(*dest)[256],byte *def, int32_t width, int32_t height, int32_t oformat, byte *newformat)
4666 {
4667 byte defFormat=(bp==8) ? tf8Bit : tf4Bit;
4668 byte format=defFormat;
4669 int32_t stile = ((imagey*TILES_PER_ROW)+imagex)+(((sely/16)*TILES_PER_ROW)+(selx/16));
4670
4671 switch(imagetype)
4672 {
4673 case ftZGP:
4674 case ftQST:
4675 case ftZQT:
4676 case ftQSU:
4677 case ftTIL:
4678 case ftBIN:
4679 case ftBMP:
4680 for(int32_t ty=0; ty<height; ty++)
4681 {
4682 for(int32_t tx=0; tx<width; tx++)
4683 {
4684 format=defFormat;
4685 switch(imagetype)
4686 {
4687 case ftZGP:
4688 case ftQST:
4689 case ftZQT:
4690 case ftQSU:
4691 case ftTIL:
4692 format=grabtilebuf[stile+((ty*TILES_PER_ROW)+tx)].format;
4693 break;
4694 }
4695
4696 bool ever_did_unmasked = false;
4697
4698 for(int32_t y=0; y<16; y++)
4699 {
4700 for(int32_t x=0; x<16; x+=2)
4701 {
4702 bool masked = (y<8 && x<8 && grabmask&1) || (y<8 && x>7 && grabmask&2) || (y>7 && x<8 && grabmask&4) || (y>7 && x>7 && grabmask&8);
4703 if (masked)
4704 {
4705 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*16)+(x)];
4706 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*16)+(x+1)];
4707 }
4708 else
4709 {
4710 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x]=getpixel(screen2,(tx*16)+x+selx,(ty*16)+y+sely);
4711 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1]=getpixel(screen2,(tx*16)+x+1+selx,(ty*16)+y+sely);
4712 ever_did_unmasked = true;
4713 }
4714 if (format == tf4Bit)
4715 {
4716 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x] &= 15;
4717 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1] &= 15;
4718 }
4719 }
4720 }
4721
4722 if (ever_did_unmasked)
4723 newformat[(ty*TILES_PER_ROW)+tx] = format;
4724 }
4725 }
4726
4727 break;
4728
4729 default:
4730 for(int32_t i=0; i<200; i++)
4731 {
4732 for(int32_t j=0; j<256; j++)
4733 {
4734 dest[i][j]=0;
4735 }
4736
4737 newformat[i] = tf4Bit;
4738 }
4739
4740 break;
4741 }
4742 }
4743
4744 static void scale_imagebuf_bitmap()
4745 {
4746 imagebuf_bitmap_scale = std::clamp(imagebuf_bitmap_scale, -10, 10);
4747
4748 float scale = IMAGEBUF_SCALE;
4749 int nw = original_imagebuf_bitmap->w * scale;
4750 int nh = original_imagebuf_bitmap->h * scale;
4751 if (nw <= 0 || nh <= 0)
4752 return;
4753
4754 BITMAP* scaled_bmp = create_bitmap_ex(8, nw, nh);
4755 if (!scaled_bmp)
4756 return;
4757
4758 stretch_blit(original_imagebuf_bitmap, scaled_bmp, 0, 0, original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, 0, 0, nw, nh);
4759 if (imagebuf != original_imagebuf_bitmap)
4760 destroy_bitmap((BITMAP*)imagebuf);
4761 imagebuf = scaled_bmp;
4762 }
4763
4764 //Grabber is not grabbing to tile pages beyond pg. 252 right now. -ZX 18th June, 2019
4765 void grab_tile(int32_t tile,int32_t &cs)
4766 {
4767 zq_allow_tile_draw_cache = true;
4768
4769 int window_w = 640+6+6, window_h = 480+25+6;
4770 int window_x=(zq_screen_w-window_w)/2;
4771 int window_y=(zq_screen_h-window_h)/2;
4772 popup_zqdialog_start(window_x,window_y,window_w,window_h,-1);
4773 int window_xofs = 0;
4774 int screen_xofs=6;
4775 int screen_yofs=25;
4776 int panel_yofs=0;
4777 int bwidth = 61*1.5;
4778 int bheight = 20*1.5;
4779 int button_x = 255*2;
4780 int grab_ok_button_y = 168*2 + 32;
4781 int leech_button_x = 117*2;
4782 int leech_button_y = 166*2 + 32;
4783 int grab_cancel_button_y = 192*2 + 32;
4784 int file_button_y = 216*2 + 32;
4785 int rec_button_x = 117*2;
4786 int rec_button_y = 192*2 + 32;
4787
4788 int screen_y1 = 24;
4789 int screen_y2 = screen_y1+320-1;
4790
4791 int crect_x = 184+190;
4792 int crect_y = 168*2 + 32;
4793 int crect_w = 8*2;
4794 int crect_h = 8*2;
4795
4796 int xrect_x = 640 + 12 - 21;
4797 int xrect_y = 5;
4798
4799 byte newtile[200][256];
4800 BITMAP *screen3=create_bitmap_ex(8, zq_screen_w, zq_screen_h);
4801 clear_bitmap(screen3);
4802 byte newformat[200];
4803
4804 memset(newtile, 0, 200*256);
4805 memset(newformat, 0, 200);
4806
4807 static EXT_LIST list[] =
4808 {
4809 { (char *)"All Files (*.*)", NULL },
4810 { (char *)"Bitmap Image (*.bmp)", (char *)"bmp" },
4811 { (char *)"GIF Image (*.gif)", (char *)"gif" },
4812 { (char *)"JPEG Image (*.jpg, *.jpeg)", (char *)"jpg,jpeg" },
4813 { (char *)"ZC Tile Export (*.til)", (char *)"til" },
4814 { (char *)"ZC Quest Template (*.zqt)", (char *)"zqt" },
4815 { (char *)"ZC Quest (*.qst)", (char *)"qst" },
4816 { (char *)"ZC Graphics Pack (*.zgp)", (char *)"zgp" },
4817 { (char *)"ZC Unencoded Quest (*.qsu)", (char *)"qsu" },
4818 { (char *)"NES ROM Image (*.nes)", (char *)"nes" },
4819 { (char *)"SNES ROM Image (*.smc)", (char *)"smc" },
4820 { (char *)"Gameboy ROM Image (*.gb)", (char *)"gb" },
4821 { (char *)"Gameboy Advance ROM Image (*.gba)", (char *)"gba" },
4822 { NULL, NULL }
4823 };
4824
4825
4826 memset(cset_reduce_table, 0, 256);
4827 memset(col_diff,0,3*128);
4828 bool bdown=false;
4829 int done=0;
4830 int pal=0;
4831 int f=0;
4832 int black=vc(0),white=vc(15);
4833 int selwidth=1, selheight=1;
4834 int selx2=0, sely2=0;
4835 bool xreversed=false, yreversed=false;
4836 bool doleech=false, dofile=false, dopal=false;
4837
4838 int jwin_pal2[jcMAX];
4839 memcpy(jwin_pal2, jwin_pal, sizeof(int)*jcMAX);
4840
4841
4842 if(imagebuf==NULL)
4843 load_imagebuf();
4844
4845 calc_cset_reduce_table(imagepal, cs);
4846 calc_cset_reduce_table_8bit(imagepal);
4847 draw_grab_window();
4848 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
4849 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
4850
4851 while(gui_mouse_b())
4852 {
4853 /* do nothing */
4854 rest(1);
4855 }
4856
4857 do
4858 {
4859 HANDLE_CLOSE_ZQDLG();
4860 if(exiting_program) break;
4861 rest(4);
4862 bool redraw=false;
4863
4864 if(keypressed())
4865 {
4866 redraw=true;
4867
4868 switch(readkey()>>8)
4869 {
4870 case KEY_F:
4871 dofile=true;
4872 break;
4873
4874 case KEY_L:
4875 doleech=true;
4876 break;
4877
4878 case KEY_P:
4879 if(imagetype==ftBMP)
4880 {
4881 dopal=true;
4882 recolor=rcNone;
4883 calc_cset_reduce_table(imagepal, cs);
4884 }
4885
4886 break;
4887
4888 case KEY_ESC:
4889 done=1;
4890 break;
4891
4892 case KEY_ENTER_PAD:
4893 case KEY_ENTER:
4894 done=2;
4895 break;
4896
4897 case KEY_DOWN:
4898 if(CHECK_CTRL_CMD) sely=zc_min(sely+1,144);
4899 else ++imagey;
4900
4901 break;
4902
4903 case KEY_UP:
4904 if(CHECK_CTRL_CMD) sely=zc_max(sely-1,0);
4905 else --imagey;
4906
4907 break;
4908
4909 case KEY_RIGHT:
4910 if(CHECK_CTRL_CMD) selx=zc_min(selx+1,304);
4911 else ++imagex;
4912
4913 break;
4914
4915 case KEY_LEFT:
4916 if(CHECK_CTRL_CMD) selx=zc_max(selx-1,0);
4917 else --imagex;
4918
4919 break;
4920
4921 case KEY_PGDN:
4922 imagey+=10;
4923 break;
4924
4925 case KEY_PGUP:
4926 imagey-=10;
4927 break;
4928
4929 case KEY_HOME:
4930 imagex=imagey=0;
4931 break;
4932
4933 case KEY_EQUALS:
4934 case KEY_PLUS_PAD:
4935 cs = (cs<13) ? cs+1:0;
4936 if(recolor==rc4Bit)
4937 calc_cset_reduce_table(imagepal, cs);
4938 break;
4939
4940 case KEY_MINUS:
4941 case KEY_MINUS_PAD:
4942 cs = (cs>0) ? cs-1:13;
4943 if(recolor==rc4Bit)
4944 calc_cset_reduce_table(imagepal, cs);
4945 break;
4946
4947 case KEY_S:
4948 if(grabmode==1) grabmode=8;
4949 else if(grabmode==8) grabmode=16;
4950 else grabmode=1;
4951
4952 break;
4953
4954 case KEY_COMMA:
4955 if (imagetype == ftBMP)
4956 {
4957 imagebuf_bitmap_scale--;
4958 if (imagebuf_bitmap_scale == 0)
4959 imagebuf_bitmap_scale = -2;
4960 scale_imagebuf_bitmap();
4961 }
4962 break;
4963 case KEY_STOP:
4964 if (imagetype == ftBMP)
4965 {
4966 imagebuf_bitmap_scale++;
4967 if (imagebuf_bitmap_scale == -1)
4968 imagebuf_bitmap_scale = 1;
4969 scale_imagebuf_bitmap();
4970 }
4971 break;
4972
4973 case KEY_1:
4974 if(recolor==rc8Bit)
4975 recolor=rcNone;
4976 //imagex=(imagex*bp)>>3;
4977 bp=1;
4978 //imagex<<=3;
4979 nesmode=false;
4980 break;
4981
4982 case KEY_2:
4983 if(recolor==rc8Bit)
4984 recolor=rcNone;
4985 //imagex=(imagex*bp)>>3;
4986 bp=2;
4987 //imagex<<=2;
4988 nesmode=false;
4989 break;
4990
4991 case KEY_N:
4992 if(recolor==rc8Bit)
4993 recolor=rcNone;
4994 //imagex=(imagex*bp)>>3;
4995 bp=2;
4996 //imagex<<=2;
4997 nesmode=true;
4998 break;
4999
5000 case KEY_4:
5001 if(recolor==rc8Bit)
5002 recolor=rcNone;
5003 //imagex=(imagex*bp)>>3;
5004 bp=4;
5005 //imagex<<=1;
5006 nesmode=false;
5007 break;
5008
5009 case KEY_8:
5010 //imagex=(imagex*bp)>>3;
5011 bp=8;
5012 break;
5013
5014 case KEY_B:
5015 if(bp==2&&!nesmode)
5016 {
5017 nesmode=true;
5018 }
5019 else
5020 {
5021 nesmode=false;
5022 bp<<=1;
5023
5024 if(bp==16)
5025 {
5026 bp=1;
5027 //imagex<<=3;
5028 }
5029 else
5030 {
5031 //imagex>>=1;
5032 }
5033 }
5034
5035 break;
5036
5037 case KEY_M:
5038 romtilemode=(romtilemode+1)%4;
5039 break;
5040
5041 case KEY_Z:
5042 if(romofs>0) --romofs;
5043
5044 break;
5045
5046 case KEY_X:
5047 ++romofs;
5048 break;
5049
5050 case KEY_R:
5051 if(pal)
5052 {
5053 dopal=true;
5054 }
5055
5056 if(recolor!=rcNone)
5057 recolor=rcNone;
5058 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5059 {
5060 bp=8;
5061 recolor=rc8Bit;
5062 calc_cset_reduce_table_8bit(imagepal);
5063 }
5064 else
5065 {
5066 if(bp==8)
5067 bp=4;
5068 recolor=rc4Bit;
5069 calc_cset_reduce_table(imagepal, cs);
5070 }
5071 break;
5072
5073 default:
5074 redraw=false;
5075 }
5076
5077 clear_keybuf();
5078
5079 if(imagex<0) imagex=0;
5080
5081 if(imagey<0) imagey=0;
5082
5083 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5084 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5085 }
5086
5087 //boogie!
5088 if(gui_mouse_b()==1 && !bdown)
5089 {
5090 int x=gui_mouse_x();
5091 int y=gui_mouse_y();
5092 if(isinRect(x,y,xrect_x, xrect_y, xrect_x + 15, xrect_y + 13))
5093 if(do_x_button(screen, xrect_x, xrect_y))
5094 done=1;
5095
5096 if(!bdown)
5097 {
5098 bool regrab=false;
5099 bdown=true;
5100 FONT* oldfont = font;
5101 font = get_zc_font(font_lfont_l);
5102
5103 if(y>=screen_y1 && y<=screen_y2)
5104 {
5105 do
5106 {
5107 HANDLE_CLOSE_ZQDLG();
5108 if(exiting_program) break;
5109 int x = (gui_mouse_x()-screen_xofs) / 2;
5110 int y = (gui_mouse_y()-screen_yofs) / 2;
5111
5112 int ox=selx,oy=sely,ow=selwidth,oh=selheight;
5113
5114 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
5115 {
5116 selx=vbound((x/grabmode)*grabmode,0,304);
5117 sely=vbound((y/grabmode)*grabmode,0,144);
5118 selx2=selx;
5119 sely2=sely;
5120 selwidth=1;
5121 selheight=1;
5122 xreversed=false;
5123 yreversed=false;
5124 }
5125 else
5126 {
5127 if(xreversed)
5128 {
5129 zc_swap(selx, selx2);
5130 xreversed=false;
5131 }
5132
5133 if(yreversed)
5134 {
5135 zc_swap(sely, sely2);
5136 yreversed=false;
5137 }
5138
5139 selx2=vbound((x/grabmode)*grabmode,0,304);
5140 sely2=vbound((y/grabmode)*grabmode,0,144);
5141 selwidth=1+(abs(selx2-selx))/16;
5142 selheight=1+(abs(sely2-sely))/16;
5143
5144 if(selx2<selx)
5145 {
5146 zc_swap(selx, selx2);
5147 xreversed=true;
5148 }
5149
5150 if(sely2<sely)
5151 {
5152 zc_swap(sely, sely2);
5153 yreversed=true;
5154 }
5155 }
5156
5157 bool changed = (ox!=selx || oy!=sely || ow!=selwidth || oh!=selheight);
5158 bool redraw = changed || !(f%8);
5159
5160 if(redraw)
5161 {
5162 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5163 if(changed)
5164 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5165 if(f&8)
5166 {
5167 static const int w = 32;
5168 rect(screen,(selx*2)+screen_xofs,(sely*2)+screen_yofs,(selx*2)+screen_xofs+((selwidth-1)*w)+(w-1),(sely*2)+screen_yofs+((selheight-1)*w)+(w-1),white);
5169 }
5170 }
5171 else custom_vsync();
5172
5173 ++f;
5174 }
5175 while(gui_mouse_b());
5176 }
5177 else if(isinRect(x,y,button_x,grab_ok_button_y,button_x+bwidth,grab_ok_button_y+bheight))
5178 {
5179 if(do_text_button(button_x,grab_ok_button_y,bwidth,bheight,"OK"))
5180 done=2;
5181 }
5182 else if(isinRect(x,y,leech_button_x,leech_button_y,leech_button_x+bwidth,leech_button_y+bheight))
5183 {
5184 if(do_text_button(leech_button_x,leech_button_y,bwidth,bheight,"Leech"))
5185 {
5186 doleech=true;
5187 }
5188 }
5189 else if(isinRect(x,y,button_x,grab_cancel_button_y,button_x+bwidth,grab_cancel_button_y+bheight))
5190 {
5191 if(do_text_button(button_x,grab_cancel_button_y,bwidth,bheight,"Cancel"))
5192 done=1;
5193 }
5194 else if(isinRect(x,y,button_x,file_button_y,button_x+bwidth,file_button_y+bheight))
5195 {
5196 if(do_text_button(button_x,file_button_y,bwidth,bheight,"File"))
5197 {
5198 dofile=true;
5199 }
5200 }
5201 else if(imagetype == ftBMP && isinRect(x,y,rec_button_x, rec_button_y, rec_button_x+bwidth, rec_button_y+bheight))
5202 {
5203 if(do_text_button(rec_button_x,rec_button_y,bwidth,bheight,"Recolor"))
5204 {
5205 if(pal)
5206 {
5207 dopal = true;
5208 }
5209
5210 if(recolor!=rcNone)
5211 recolor=rcNone;
5212 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5213 {
5214 bp=8;
5215 recolor=rc8Bit;
5216 calc_cset_reduce_table_8bit(imagepal);
5217 }
5218 else
5219 {
5220 if(bp==8)
5221 bp=4;
5222 recolor=rc4Bit;
5223 calc_cset_reduce_table(imagepal, cs);
5224 }
5225 redraw=true;
5226 }
5227 }
5228 else if(isinRect(x,y+panel_yofs,crect_x,crect_y,crect_x+(16),crect_y+crect_h-1))
5229 {
5230 regrab=true;
5231 grabmask^=1;
5232 }
5233 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y,crect_x+(32)-1,crect_y+crect_h-1))
5234 {
5235 regrab=true;
5236 grabmask^=2;
5237 }
5238 else if(isinRect(x,y+panel_yofs,crect_x,crect_y+crect_h,crect_x+(16)-1,crect_y+crect_h+crect_h-1))
5239 {
5240 regrab=true;
5241 grabmask^=4;
5242 }
5243 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y+crect_h,crect_x+(32)-1,crect_y+crect_h+crect_h-1))
5244 {
5245 regrab=true;
5246 grabmask^=8;
5247 }
5248
5249 if(regrab)
5250 {
5251 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5252 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5253 redraw=true;
5254 }
5255
5256 font = oldfont;
5257 }
5258 }
5259
5260 if(gui_mouse_b()==0)
5261 bdown=false;
5262
5263 if(dofile)
5264 {
5265 if (prompt_for_existing_file_compat("Load File", "", list, imagepath, true))
5266 {
5267 zc_set_palette(RAMpal);
5268 pal=0;
5269 white=vc(15);
5270 black=vc(0);
5271 strcpy(imagepath,temppath);
5272 load_imagebuf();
5273 imagex=imagey=0;
5274 calc_cset_reduce_table(imagepal, cs);
5275 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5276 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5277 }
5278
5279 while(key[KEY_ESC])
5280 {
5281 poll_keyboard();
5282 /* do nothing */
5283 rest(1);
5284 }
5285
5286 clear_keybuf();
5287 dofile=false;
5288 redraw=true;
5289 }
5290
5291 if(doleech)
5292 {
5293 if(leech_tiles(newtilebuf,tile,cs))
5294 {
5295 done=1;
5296 }
5297 else
5298 {
5299 while(key[KEY_ESC])
5300 {
5301 poll_keyboard();
5302 /* do nothing */
5303 rest(1);
5304 }
5305
5306 clear_keybuf();
5307 redraw=true;
5308 }
5309
5310 doleech=false;
5311 }
5312
5313 if(dopal)
5314 {
5315 pal^=1;
5316
5317 if(pal)
5318 {
5319 get_bw(imagepal,black,white);
5320
5321 jwin_pal[jcBOX] =imagepal_table.data[0][jwin_pal[jcBOX]];
5322 jwin_pal[jcLIGHT] =imagepal_table.data[0][jwin_pal[jcLIGHT]];
5323 jwin_pal[jcMEDLT] =imagepal_table.data[0][jwin_pal[jcMEDLT]];
5324 jwin_pal[jcMEDDARK]=imagepal_table.data[0][jwin_pal[jcMEDDARK]];
5325 jwin_pal[jcDARK] =imagepal_table.data[0][jwin_pal[jcDARK]];
5326 jwin_pal[jcBOXFG] =imagepal_table.data[0][jwin_pal[jcBOXFG]];
5327 jwin_pal[jcTITLEL] =imagepal_table.data[0][jwin_pal[jcTITLEL]];
5328 jwin_pal[jcTITLER] =imagepal_table.data[0][jwin_pal[jcTITLER]];
5329 jwin_pal[jcTITLEFG]=imagepal_table.data[0][jwin_pal[jcTITLEFG]];
5330 jwin_pal[jcTEXTBG] =imagepal_table.data[0][jwin_pal[jcTEXTBG]];
5331 jwin_pal[jcTEXTFG] =imagepal_table.data[0][jwin_pal[jcTEXTFG]];
5332 jwin_pal[jcSELBG] =imagepal_table.data[0][jwin_pal[jcSELBG]];
5333 jwin_pal[jcSELFG] =imagepal_table.data[0][jwin_pal[jcSELFG]];
5334 gui_bg_color=jwin_pal[jcBOX];
5335 gui_fg_color=jwin_pal[jcBOXFG];
5336 jwin_set_colors(jwin_pal);
5337 }
5338 else
5339 {
5340 white=vc(15);
5341 black=vc(0);
5342
5343 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5344 gui_bg_color=jwin_pal[jcBOX];
5345 gui_fg_color=jwin_pal[jcBOXFG];
5346 jwin_set_colors(jwin_pal);
5347 }
5348
5349 zc_set_palette_range(pal?imagepal:RAMpal,0,255,false);
5350
5351 dopal=false;
5352 redraw=true;
5353 }
5354
5355 if(redraw)
5356 {
5357 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5358 }
5359 else
5360 {
5361 custom_vsync();
5362 }
5363
5364 if((f%8)==0)
5365 {
5366 stretch_blit(screen2,screen3,0, 0, zq_screen_w, zq_screen_h, 0, 0, zq_screen_w*2, zq_screen_h*2);
5367
5368 int selxl = selx* 2;
5369 int selyl = sely* 2;
5370 int w = 32;
5371
5372 if(f&8)
5373 rect(screen3,selxl,selyl,selxl+((selwidth-1)*w)+(w-1),selyl+((selheight-1)*w)+(w-1),white);
5374
5375 blit(screen3,screen,selxl,selyl,selxl+screen_xofs,selyl+screen_yofs,selwidth*w,selheight*w);
5376 }
5377
5378 // SCRFIX();
5379 ++f;
5380
5381 }
5382 while(!done);
5383
5384 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5385 gui_bg_color=jwin_pal[jcBOX];
5386 gui_fg_color=jwin_pal[jcBOXFG];
5387 jwin_set_colors(jwin_pal);
5388
5389
5390 if(done==2)
5391 {
5392 go_tiles();
5393 saved=false;
5394
5395 for(int y=0; y<selheight; y++)
5396 {
5397 for(int x=0; x<selwidth; x++)
5398 {
5399 int temptile=tile+((TILES_PER_ROW*y)+x);
5400 int format=(bp==8) ? tf8Bit : tf4Bit;
5401
5402 if(newtilebuf[temptile].data!=NULL)
5403 free(newtilebuf[temptile].data);
5404
5405 newtilebuf[temptile].format=format;
5406 newtilebuf[temptile].data=(byte *)malloc(tilesize(format));
5407
5408 if(newtilebuf[temptile].data==NULL)
5409 {
5410 Z_error_fatal("Unable to initialize tile #%d.\n", temptile);
5411 break;
5412 }
5413
5414 for(int i=0; i<256; i++)
5415 {
5416 // newtilebuf[temptile].data[i] = cset_reduce_table[newtile[(TILES_PER_ROW*y)+x][i]];
5417 newtilebuf[temptile].data[i] = newtile[(TILES_PER_ROW*y)+x][i];
5418 }
5419
5420 // unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
5421 }
5422 }
5423 }
5424
5425 destroy_bitmap(screen3);
5426
5427 if(pal)
5428 zc_set_palette(RAMpal);
5429
5430 recolor=rcNone;
5431 calc_cset_reduce_table(imagepal, cs);
5432 register_blank_tiles();
5433 popup_zqdialog_end();
5434
5435 zq_allow_tile_draw_cache = false;
5436 }
5437
5438 int32_t show_only_unused_tiles=4; //1 bit: hide used, 2 bit: hide unused, 4 bit: hide blank
5439 bool tile_is_used(int32_t tile)
5440 {
5441 return used_tile_table[tile];
5442 }
5443 void draw_tiles(int32_t first,int32_t cs, int32_t f)
5444 {
5445 draw_tiles(screen2, first, cs, f, true);
5446 }
5447 void draw_tiles(BITMAP* dest,int32_t first,int32_t cs, int32_t f, bool large, bool true_empty)
5448 {
5449 clear_bitmap(dest);
5450 BITMAP *buf = create_bitmap_ex(8,16,16);
5451
5452 int32_t w = 16;
5453 int32_t h = 16;
5454
5455 if(large)
5456 {
5457 w *=2;
5458 h *=2;
5459 }
5460
5461 for(int32_t i=0; i<TILES_PER_PAGE; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
5462 {
5463 int32_t x = (i%TILES_PER_ROW)<<4;
5464 int32_t y = (i/TILES_PER_ROW)<<4;
5465 int32_t l = 16;
5466
5467 if(large)
5468 {
5469 x*=2;
5470 y*=2;
5471 l*=2;
5472 }
5473
5474 l-=2;
5475
5476 if((HIDE_USED && tile_is_used(first+i) && !blank_tile_table[first+i]) // 1 bit: hide used
5477 || (HIDE_UNUSED && !tile_is_used(first+i) && !blank_tile_table[first+i]) // 2 bit: hide unused
5478 || (HIDE_BLANK && blank_tile_table[first+i])) // 4 bit: hide blank
5479 {
5480 if(!true_empty) //Use pure color 0; no effects
5481 {
5482 if (InvalidBG == 2)
5483 {
5484 draw_checkerboard(dest, x, y, w);
5485 }
5486 else if(InvalidBG == 1)
5487 {
5488 for(int32_t dy=0; dy<=l+1; dy++)
5489 {
5490 for(int32_t dx=0; dx<=l+1; dx++)
5491 {
5492 dest->line[dy+(y)][dx+(x)]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5493 }
5494 }
5495 }
5496 else
5497 {
5498 for(int32_t dy=0; dy<=l+1; dy++)
5499 {
5500 for(int32_t dx=0; dx<=l+1; dx++)
5501 {
5502 dest->line[dy+(y)][dx+(x)]=vc(0);
5503 }
5504 }
5505 rect(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5506 line(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5507 line(dest, (x)+1,(y)+l, (x)+l, (y)+1, vc(15));
5508 }
5509 }
5510 }
5511 else
5512 {
5513 puttile16(buf,first+i,0,0,cs,0);
5514 stretch_blit(buf,dest,0,0,16,16,x,y,w,h);
5515 }
5516
5517 if((f%32)<=16 && large && !HIDE_8BIT_MARKER && newtilebuf[first+i].format==tf8Bit)
5518 {
5519 textprintf_ex(dest,get_zc_font(font_z3smallfont),(x)+l-3,(y)+l-3,vc(int32_t((f%32)/6)+10),-1,"8");
5520 }
5521 }
5522
5523 destroy_bitmap(buf);
5524 }
5525
5526 void tile_info_0(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,bool rect_sel)
5527 {
5528 int32_t yofs=3;
5529 BITMAP *buf = create_bitmap_ex(8,16,16);
5530 int32_t mul = 2;
5531 FONT *tfont = get_zc_font(font_pfont);
5532
5533 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5534 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5535 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5536 tfont = get_zc_font(font_lfont_l);
5537
5538 // Copied tile and numbers
5539 jwin_draw_frame(screen2,(34*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5540 int32_t coldiff=TILECOL(copy)-TILECOL(copy+copycnt-1);
5541 if(copy>=0)
5542 {
5543 puttile16(buf,rect_sel&&coldiff>0?copy-coldiff:copy,0,0,cs,0);
5544 stretch_blit(buf,screen2,0,0,16,16,34*mul,216*mul+yofs,16*mul,16*mul);
5545
5546 if(copycnt>1)
5547 {
5548 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
5549 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
5550 }
5551 else
5552 {
5553 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
5554 }
5555 }
5556 else // No tiles copied
5557 {
5558 if (InvalidBG == 2)
5559 {
5560 draw_checkerboard(screen2, 34 * mul, 216 * mul + yofs, 16 * mul);
5561 }
5562 else if(InvalidBG == 1)
5563 {
5564 for(int32_t dy=0; dy<16*mul; dy++)
5565 {
5566 for(int32_t dx=0; dx<16*mul; dx++)
5567 {
5568 screen2->line[(216*mul+yofs+dy)][36*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5569 }
5570 }
5571 }
5572 else
5573 {
5574 rectfill(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(0));
5575 rect(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5576 line(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5577 line(screen2, 34*mul, ((216+15)*mul)+yofs, (34+15)*mul, (216*mul)+yofs, vc(15));
5578 }
5579 }
5580
5581
5582 // Current tile
5583 jwin_draw_frame(screen2,(104*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5584 puttile16(buf,tile,0,0,cs,0);
5585 stretch_blit(buf,screen2,0,0,16,16,104*mul,216*mul+yofs,16*mul,16*mul);
5586
5587 // Current selection mode
5588 jwin_draw_frame(screen2,(127*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5589 stretch_blit(select_bmp[rect_sel?1:0],screen2,0,0,16,16,127*mul,216*mul+yofs,16*mul,16*mul);
5590
5591 if(tile>tile2)
5592 {
5593 zc_swap(tile,tile2);
5594 }
5595
5596 char tbuf[8];
5597 tbuf[0]=0;
5598
5599 if(tile2!=tile)
5600 {
5601 sprintf(tbuf,"-%d",tile2);
5602 }
5603
5604 // Current tile and CSet text
5605 textprintf_ex(screen2,tfont,55*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cs: %d",cs);
5606 textprintf_right_ex(screen2,tfont,99*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile:");
5607 textprintf_right_ex(screen2,tfont,99*mul,224*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,tbuf);
5608
5609 FONT *tf = font;
5610 font = tfont;
5611
5612 draw_text_button(screen2,150*mul,213*mul+yofs,28*mul,21*mul,"&Grab",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5613 draw_text_button(screen2,(150+28)*mul,213*mul+yofs,28*mul,21*mul,"&Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5614 draw_text_button(screen2,(150+28*2)*mul,213*mul+yofs,28*mul,21*mul,"Export",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5615 draw_text_button(screen2,(150+28*3)*mul,213*mul+yofs,28*mul,21*mul,"Recolor",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5616 draw_text_button(screen2,(150+28*4)*mul,213*mul+yofs,28*mul,21*mul,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5617
5618 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5619 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5620 textprintf_centre_ex(screen2,tfont,(305*mul+4),220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5621 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5622
5623 font = tf;
5624
5625 int32_t w = 640;
5626 int32_t h = 480;
5627 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5628 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5629 int32_t screen_xofs=window_xofs+6;
5630 int32_t screen_yofs=window_yofs+25;
5631
5632 custom_vsync();
5633 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5634 SCRFIX();
5635 destroy_bitmap(buf);
5636 }
5637
5638 void tile_info_1(int32_t oldtile,int32_t oldflip,int32_t oldcs,int32_t tile,int32_t flip,int32_t cs,int32_t copy,int32_t page, bool always_use_flip)
5639 {
5640 int32_t yofs=3;
5641 BITMAP *buf = create_bitmap_ex(8,16,16);
5642 int32_t mul = 2;
5643 FONT *tfont = get_zc_font(font_pfont);
5644
5645 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5646 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5647 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5648 tfont = get_zc_font(font_lfont_l);
5649
5650 jwin_draw_frame(screen2,(124*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5651
5652 if(copy>=0)
5653 {
5654 puttile16(buf,copy,0,0,cs,flip);
5655 stretch_blit(buf,screen2,0,0,16,16,124*mul,216*mul+yofs,16*mul,16*mul);
5656 }
5657 else
5658 {
5659 if (InvalidBG == 2)
5660 {
5661 draw_checkerboard(screen2, 124 * mul, 216 * mul + yofs, 16 * mul);
5662 }
5663 else if(InvalidBG == 1)
5664 {
5665 for(int32_t dy=0; dy<16*mul; dy++)
5666 {
5667 for(int32_t dx=0; dx<16*mul; dx++)
5668 {
5669 screen2->line[216*mul+yofs+dy][124*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5670 }
5671 }
5672 }
5673 else
5674 {
5675 rectfill(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(0));
5676 rect(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5677 line(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5678 line(screen2, 124*mul, ((216+15)*mul)+yofs, (124+15)*mul, (216*mul)+yofs, vc(15));
5679 }
5680 }
5681
5682 jwin_draw_frame(screen2,(8*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5683 puttile16(buf,oldtile,0,0, oldcs, oldflip);
5684 stretch_blit(buf,screen2,0,0,16,16,8*mul,216*mul+yofs,16*mul,16*mul);
5685
5686 textprintf_right_ex(screen2,tfont,56*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Old Tile:");
5687 textprintf_ex(screen2,tfont,60*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldtile);
5688
5689 textprintf_right_ex(screen2,tfont,56*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5690 textprintf_ex(screen2,tfont,60*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldcs);
5691
5692 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5693 {
5694 textprintf_right_ex(screen2,tfont,56*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5695 textprintf_ex(screen2,tfont,60*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldflip);
5696 }
5697
5698 jwin_draw_frame(screen2,(148*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5699 puttile16(buf,tile,0,0, cs,
5700 (oldflip>0 || always_use_flip)?flip:0); // Suppress Flip for this usage
5701 stretch_blit(buf,screen2,0,0,16,16,148*mul,216*mul+yofs,16*mul,16*mul);
5702
5703 textprintf_right_ex(screen2,tfont,201*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"New Tile:");
5704 textprintf_ex(screen2,tfont,205*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",tile);
5705 textprintf_right_ex(screen2,tfont,201*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5706 textprintf_ex(screen2,tfont,205*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",cs);
5707
5708 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5709 {
5710 textprintf_right_ex(screen2,tfont,201*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5711 textprintf_ex(screen2,tfont,205*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",flip);
5712 }
5713
5714 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5715 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5716 textprintf_centre_ex(screen2,tfont,309*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5717 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5718
5719
5720 int32_t w = 640;
5721 int32_t h = 480;
5722 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5723 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5724 int32_t screen_xofs=window_xofs+6;
5725 int32_t screen_yofs=window_yofs+25;
5726
5727 custom_vsync();
5728 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5729 SCRFIX();
5730 destroy_bitmap(buf);
5731 }
5732 /*
5733 void reset_tile(tiledata *buf, int32_t t, int32_t format=1)
5734 {
5735 buf[t].format=format;
5736 if (buf[t].data!=NULL)
5737 {
5738 free(buf[t].data);
5739 }
5740 buf[t].data=(byte *)malloc(tilesize(buf[t].format));
5741 if (buf[t].data==NULL)
5742 {
5743 Z_error_fatal("Unable to initialize tile #%d.\n", t);
5744 }
5745 for(int32_t i=0; i<tilesize(buf[t].format); i++)
5746 {
5747 buf[t].data[i]=0;
5748 }
5749 }
5750 */
5751
5752 int32_t hide_used()
5753 {
5754 show_only_unused_tiles ^= 1;
5755 return D_O_K;
5756 }
5757 int32_t hide_unused()
5758 {
5759 show_only_unused_tiles ^= 2;
5760 return D_O_K;
5761 }
5762 int32_t hide_blank()
5763 {
5764 show_only_unused_tiles ^= 4;
5765 return D_O_K;
5766 }
5767 int32_t hide_8bit_marker()
5768 {
5769 show_only_unused_tiles ^= 8;
5770 return D_O_K;
5771 }
5772
5773 enum
5774 {
5775 MENUID_SELTILE_VIEW_HIDE_USED,
5776 MENUID_SELTILE_VIEW_HIDE_UNUSED,
5777 MENUID_SELTILE_VIEW_HIDE_BLANK,
5778 MENUID_SELTILE_VIEW_HIDE_8BIT,
5779 };
5780
1/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
9 static NewMenu select_tile_view_menu
5781 45 {
5782
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Used", hide_used, MENUID_SELTILE_VIEW_HIDE_USED },
5783
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Unused", hide_unused, MENUID_SELTILE_VIEW_HIDE_UNUSED },
5784
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Blank", hide_blank, MENUID_SELTILE_VIEW_HIDE_BLANK },
5785
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide 8-bit marker", hide_8bit_marker, MENUID_SELTILE_VIEW_HIDE_8BIT },
5786 };
5787
5788 9 static std::function<void(int)> select_tile_color_depth_cb;
5789
5790 static void set_tile_color_depth_4()
5791 {
5792 select_tile_color_depth_cb(tf4Bit);
5793 }
5794 static void set_tile_color_depth_8()
5795 {
5796 select_tile_color_depth_cb(tf8Bit);
5797 }
5798 enum
5799 {
5800 MENUID_SELTILE_COLOR_DEPTH_4_BIT,
5801 MENUID_SELTILE_COLOR_DEPTH_8_BIT,
5802 };
5803
1/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
9 static NewMenu select_tile_color_depth_menu
5804 27 {
5805
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "4-bit", set_tile_color_depth_4, MENUID_SELTILE_COLOR_DEPTH_4_BIT },
5806
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "8-bit", set_tile_color_depth_8, MENUID_SELTILE_COLOR_DEPTH_8_BIT },
5807 };
5808
5809 //returns the row the tile is in on its page
5810 int32_t tile_page_row(int32_t tile)
5811 {
5812 return TILEROW(tile)-(TILEPAGE(tile)*TILE_ROWS_PER_PAGE);
5813 }
5814
5815 enum {ti_none, ti_encompass, ti_broken};
5816
5817 //striped check and striped selection
5818 int32_t move_intersection_ss(newcombo &cmb, int32_t selection_first, int32_t selection_last, int32_t offset = 0)
5819 {
5820 int32_t cmb_first = cmb.o_tile;
5821 int32_t cmb_last = cmb.o_tile;
5822 do
5823 {
5824 cmb_last = cmb.tile;
5825 animate(cmb, true);
5826 }
5827 while(cmb.tile != cmb.o_tile);
5828 reset_combo_animation(cmb);
5829 cmb_first += offset;
5830 cmb_last += offset;
5831
5832 if(cmb_first > selection_last || cmb_last < selection_first)
5833 return ti_none;
5834 if(cmb_first >= selection_first && cmb_last <= selection_last)
5835 return ti_encompass;
5836
5837 do
5838 {
5839 if(cmb.tile+offset >= selection_first && cmb.tile+offset <= selection_last)
5840 {
5841 reset_combo_animation(cmb);
5842 return ti_broken; //contained, but non-encompassing.
5843 }
5844 animate(cmb, true);
5845 }
5846 while(cmb.tile != cmb.o_tile);
5847 reset_combo_animation(cmb);
5848 return ti_none;
5849 }
5850 int32_t move_intersection_ss(int32_t check_first, int32_t check_last, int32_t selection_first, int32_t selection_last)
5851 {
5852 // if selection is before or after check...
5853 if((check_first>selection_last)||(selection_first>check_last))
5854 {
5855 return ti_none;
5856 }
5857
5858 // if selection envelopes check
5859 if((selection_first<=check_first)&&(selection_last>=check_last))
5860 {
5861 return ti_encompass; //encompass
5862 }
5863
5864 //everything else is a break
5865 return ti_broken; //intersect
5866 }
5867
5868
5869
5870 //rectangular check and striped selection
5871 int32_t move_intersection_rs(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_first, int32_t selection_last)
5872 {
5873 int32_t ret1=-1, ret2=-1;
5874
5875 for(int32_t i=0; i<check_height; ++i)
5876 {
5877 int32_t check_first=((check_top+i)*TILES_PER_ROW)+check_left;
5878 int32_t check_last=check_first+check_width-1;
5879 ret2=move_intersection_ss(check_first, check_last, selection_first, selection_last);
5880
5881 if(ret2==ti_broken)
5882 {
5883 return ti_broken;
5884 }
5885
5886 ret1=(ret2==ti_encompass?ti_encompass:ret1);
5887 }
5888
5889 if(ret1==ti_encompass)
5890 {
5891 if((TILEROW(selection_first)<=check_top) &&
5892 (TILEROW(selection_last)>=(check_top+check_height-1)))
5893 {
5894 return ti_encompass;
5895 }
5896 else
5897 {
5898 return ti_broken;
5899 }
5900 }
5901
5902 return ti_none;
5903 }
5904
5905
5906 //striped check and rectangular selection
5907 int32_t move_intersection_sr(newcombo &cmb, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height, int32_t offset = 0)
5908 {
5909 if(selection_width < TILES_PER_ROW)
5910 {
5911 int32_t cmb_first = cmb.o_tile;
5912 int32_t cmb_last = cmb.o_tile;
5913 do
5914 {
5915 cmb_last = cmb.tile;
5916 animate(cmb, true);
5917 }
5918 while(cmb.tile != cmb.o_tile);
5919 reset_combo_animation(cmb);
5920 cmb_first += offset;
5921 cmb_last += offset;
5922
5923 if((TILEROW(cmb_first)>=selection_top) &&
5924 (TILEROW(cmb_last)<=selection_top+selection_height-1) &&
5925 (TILECOL(cmb_first)>=selection_left) &&
5926 (TILECOL(cmb_last)<=TILECOL(selection_left+selection_width-1)))
5927 {
5928 return ti_encompass;
5929 }
5930 else if((cmb_last<selection_top*TILES_PER_ROW+selection_left) ||
5931 (cmb_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
5932 {
5933 return ti_none;
5934 }
5935
5936 if(TILEROW(cmb_first) == TILEROW(cmb_last))
5937 {
5938 int32_t firstcol = TILECOL(cmb_first);
5939 int32_t lastcol = TILECOL(cmb_last);
5940
5941 if(lastcol < selection_left || firstcol >= selection_left+selection_width)
5942 return ti_none;
5943 else //handle skip x
5944 {
5945 do
5946 {
5947 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width)
5948 {
5949 reset_combo_animation(cmb);
5950 return ti_broken;
5951 }
5952 animate(cmb, true);
5953 }
5954 while(cmb.tile != cmb.o_tile);
5955 reset_combo_animation(cmb);
5956 return ti_none;
5957 }
5958 }
5959 else //multi-row combo...
5960 {
5961 int32_t row = TILEROW(cmb_first);
5962
5963 do
5964 {
5965 if(row < selection_top || row > selection_top+selection_height-1)
5966 {
5967 //This row isn't in the selection; skip to next row
5968 do
5969 {
5970 animate(cmb,true);
5971 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5972 }
5973 while(TILEROW(cmb.tile) == row);
5974 row = TILEROW(cmb.tile);
5975 continue;
5976 }
5977
5978 //This row IS in the selection; check each tile.
5979 do
5980 {
5981 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width-1)
5982 {
5983 reset_combo_animation(cmb);
5984 return ti_broken;
5985 }
5986 animate(cmb, true);
5987 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5988 }
5989 while(TILEROW(cmb.tile) == row);
5990 row = TILEROW(cmb.tile);
5991 }
5992 while(cmb.tile != cmb.o_tile);
5993
5994 return ti_none; //...Theoretically unreachable, but if it DOES get here, it's done.
5995 }
5996 }
5997
5998 return move_intersection_ss(cmb, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1, offset);
5999 }
6000 int32_t move_intersection_sr(int32_t check_first, int32_t check_last, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6001 {
6002 if(selection_width < TILES_PER_ROW)
6003 {
6004 if((check_last-check_first+1<=selection_width) &&
6005 (TILEROW(check_first)>=selection_top) &&
6006 (TILEROW(check_last)<=selection_top+selection_height-1) &&
6007 (TILECOL(check_first)>=selection_left) &&
6008 (TILECOL(check_last)<=TILECOL(selection_left+selection_width-1)))
6009 {
6010 return ti_encompass;
6011 }
6012 else if((check_last<selection_top*TILES_PER_ROW+selection_left) ||
6013 (check_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
6014 {
6015 return ti_none;
6016 }
6017
6018 //else if (selection_top*TILES_PER_ROW+selection_left<check_first && (selection_top+1)*TILES_PER_ROW+selection_left>check_last)
6019
6020 //one last base case: the strip we're interested in only lies along one row
6021 if(check_first/TILES_PER_ROW == check_last/TILES_PER_ROW)
6022 {
6023 int32_t cfcol = check_first%TILES_PER_ROW;
6024 int32_t clcol = check_last%TILES_PER_ROW;
6025
6026 if(clcol < selection_left || cfcol >= selection_left+selection_width)
6027 return ti_none;
6028 else
6029 return ti_broken;
6030 }
6031 else
6032 {
6033 //recursively cut the strip into substrips which lie entirely on one row
6034 int32_t currow = check_first/TILES_PER_ROW;
6035 int32_t endrow = check_last/TILES_PER_ROW;
6036 int32_t accum = 0;
6037 accum |= move_intersection_sr(check_first,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6038
6039 for(++currow; currow<endrow; currow++)
6040 {
6041 accum |= move_intersection_sr(currow*TILES_PER_ROW,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6042 }
6043
6044 accum |= move_intersection_sr(currow*TILES_PER_ROW, check_last,selection_left,selection_top,selection_width,selection_height);
6045
6046 if(accum > 0)
6047 return ti_broken;
6048
6049 return ti_none;
6050 }
6051 }
6052
6053 return move_intersection_ss(check_first, check_last, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1);
6054 }
6055
6056 //rectangular check and rectangular selection
6057 int32_t move_intersection_rr(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6058 {
6059 if((check_left>=selection_left) &&
6060 (check_left+check_width<=selection_left+selection_width) &&
6061 (check_top>=selection_top) &&
6062 (check_top+check_height<=selection_top+selection_height))
6063 {
6064 return ti_encompass;
6065 }
6066 else
6067 {
6068 for(int32_t i=check_top; i<check_top+check_height; ++i)
6069 {
6070 if(move_intersection_rs(selection_left, selection_top, selection_width, selection_height, i*TILES_PER_ROW+check_left, i*TILES_PER_ROW+check_left+check_width-1)!=ti_none)
6071 {
6072 return ti_broken;
6073 }
6074 }
6075 }
6076
6077 return ti_none;
6078 }
6079
6080
6081
6082
6083 static DIALOG move_textbox_list_dlg[] =
6084 {
6085 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
6086 9 { jwin_win_proc, 0, 0, 300, 212, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6087 9 { jwin_ctext_proc, 150, 18, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6088 9 { jwin_ctext_proc, 150, 28, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6089 9 { jwin_textbox_proc, 12, 40, 277, 138, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6090 9 { jwin_button_proc, 80, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
6091 9 { jwin_button_proc, 160, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
6092 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
6093 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
6094 };
6095
6096 bool popup_move_textbox_dlg(string const& msg, char* textbox, char const* title)
6097 {
6098 char buf1[512] = {0};
6099 char buf2[512] = {0};
6100 large_dialog(move_textbox_list_dlg);
6101 DIALOG& tbox = move_textbox_list_dlg[3];
6102 {
6103 FONT* f = tbox.dp2 ? (FONT*)tbox.dp2 : get_custom_font(CFONT_GUI);
6104 int indx = 0, word_indx = 0;
6105 for(char c : msg)
6106 {
6107 if(c == ' ' || c == '\n')
6108 word_indx = indx;
6109 buf1[indx++] = c;
6110 if(c == '\n' || text_length(f, buf1) >= tbox.w)
6111 {
6112 buf1[word_indx] = 0;
6113 strcpy(buf2, msg.c_str()+word_indx+1);
6114 break;
6115 }
6116 }
6117 }
6118
6119 move_textbox_list_dlg[0].dp = (void*)title;
6120 move_textbox_list_dlg[0].dp2 = get_zc_font(font_lfont);
6121 move_textbox_list_dlg[1].dp = buf1;
6122 move_textbox_list_dlg[2].dp = buf2;
6123 tbox.dp = textbox;
6124 tbox.d2 = 0;
6125 auto tby = tbox.y;
6126 auto tbh = tbox.h;
6127 if(!buf2[0])
6128 {
6129 auto diff = move_textbox_list_dlg[2].h;
6130 tbox.y -= diff;
6131 tbox.h += diff;
6132 }
6133
6134 int32_t ret=do_zqdialog(move_textbox_list_dlg,2);
6135 position_mouse_z(0);
6136 tbox.y = tby;
6137 tbox.h = tbh;
6138
6139 return ret == 4;
6140 }
6141
6142 int32_t quick_select_3(int32_t a, int32_t b, int32_t c, int32_t d)
6143 {
6144 return a==0?b:a==1?c:d;
6145 }
6146
6147 bool TileMoveList::process(std::unique_ptr<BaseTileRef>& ref, TileMoveProcess const& proc, bool is_dest)
6148 {
6149 TileRefCombo* combo_ref = dynamic_cast<TileRefCombo*>(ref.get());
6150 int i = ti_none;
6151 auto t = ref->getTile() + ref->offset();
6152
6153 if(combo_ref)
6154 {
6155 if(proc.rect)
6156 i=move_intersection_sr(*combo_ref->combo, proc._l, proc._t, proc._w, proc._h);
6157 else i=move_intersection_ss(*combo_ref->combo, proc._first, proc._last);
6158 }
6159 else if(proc.rect)
6160 {
6161 if(ref->h > 1)
6162 i=move_intersection_rr(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._l, proc._t, proc._w, proc._h);
6163 else i=move_intersection_sr(t, t+ref->w-1, proc._l, proc._t, proc._w, proc._h);
6164 }
6165 else
6166 {
6167 if(ref->h > 1)
6168 i=move_intersection_rs(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._first, proc._last);
6169 else i=move_intersection_ss(t, t+ref->w-1, proc._first, proc._last);
6170 }
6171
6172 bool in = i != ti_none, out = i != ti_encompass;
6173 for(size_t q = 0; !(in&&out) && q < ref->extra_rects.size(); ++q)
6174 {
6175 auto [ex_t,ex_w,ex_h] = ref->extra_rects[q];
6176 if(proc.rect)
6177 i = move_intersection_rr(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._l, proc._t, proc._w, proc._h);
6178 else i = move_intersection_rs(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._first, proc._last);
6179 if(i != ti_none)
6180 in = true;
6181 if(i != ti_encompass)
6182 out = true;
6183 }
6184 i = in ? (out ? ti_broken : ti_encompass) : ti_none;
6185
6186 if(i != ti_none && ref->getTile() != 0)
6187 {
6188 if(mode == Mode::CHECK_ALL)
6189 {
6190 move_refs.emplace_back(std::move(ref));
6191 return true;
6192 }
6193 else if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6194 {
6195 if(warning_flood || warning_list.tellp() >= 65000)
6196 {
6197 if(!warning_flood)
6198 warning_list << "...\n...\n...\nmany others";
6199 warning_flood = true;
6200 }
6201 else
6202 warning_list << ref->name << '\n';
6203 }
6204 else if(i==ti_encompass)
6205 {
6206 move_refs.emplace_back(std::move(ref));
6207 return true;
6208 }
6209 }
6210 return false;
6211 }
6212
6213 bool TileMoveList::check_prot()
6214 {
6215 if(!TileProtection)
6216 return true;
6217 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Tile Warning");
6218
6219 warning_flood = false;
6220 warning_list.clear();
6221
6222 return ret;
6223 }
6224
6225 void TileMoveList::add_diff(int diff)
6226 {
6227 for(auto& ref : move_refs)
6228 ref->addTile(diff);
6229 }
6230
6231 //from 'combo.h'
6232 bool ComboMoveList::process(std::unique_ptr<BaseComboRef>& ref, ComboMoveProcess const& proc, bool is_dest)
6233 {
6234 int i = ti_none;
6235 auto c = ref->getCombo();
6236
6237 if(ref->no_move)
6238 processed_combos[c] = true;
6239 else processed_combos[c]; //inserts element if does not exist
6240 i = move_intersection_ss(c, c, proc._first, proc._last);
6241
6242 if(i != ti_none && ref->getCombo() != 0)
6243 {
6244 if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6245 {
6246 if(ComboProtection)
6247 {
6248 if(warning_flood || warning_list.tellp() >= 65000)
6249 {
6250 if(!warning_flood)
6251 warning_list << "...\n...\n...\nmany others";
6252 warning_flood = true;
6253 }
6254 else
6255 warning_list << ref->name << '\n';
6256 }
6257 }
6258 else if(i==ti_encompass)
6259 {
6260 move_refs.emplace_back(std::move(ref));
6261 return true;
6262 }
6263 }
6264 return false;
6265 }
6266
6267 bool ComboMoveList::check_prot()
6268 {
6269 if(!ComboProtection)
6270 return true;
6271 vector<set<int> const*> subset = combo_links.subset(processed_combos);
6272 bool subset_header = false;
6273 for(int q = 0; q < 2; ++q)
6274 {
6275 bool is_dest = (q==1);
6276 if(!is_dest && !source_process)
6277 continue;
6278 ComboMoveProcess const& proc = is_dest ? dest_process : *source_process;
6279 for(auto it = subset.begin(); it != subset.end();)
6280 {
6281 auto s = *it;
6282 if(warning_flood || warning_list.tellp() >= 65000)
6283 {
6284 if(!warning_flood)
6285 warning_list << "...\n...\n...\nmany others";
6286 warning_flood = true;
6287 break;
6288 }
6289 set<int> in_set, out_set;
6290 bool no_move = is_dest;
6291 for(int c : *s)
6292 {
6293 int i = move_intersection_ss(c, c, proc._first, proc._last);
6294 if(i != ti_none)
6295 in_set.insert(c);
6296 if(i != ti_encompass)
6297 out_set.insert(c);
6298 if(!no_move)
6299 {
6300 auto it = processed_combos.find(c);
6301 if(it != processed_combos.end() && it->second)
6302 no_move = true;
6303 }
6304 }
6305 int i = in_set.empty() ? ti_none : (out_set.empty() ? ti_encompass : ti_broken);
6306 if(i == ti_encompass && !no_move)
6307 {
6308 it = subset.erase(it);
6309 continue;
6310 }
6311 if(i == ti_none)
6312 {
6313 ++it;
6314 continue;
6315 }
6316
6317 if(!subset_header)
6318 {
6319 subset_header = true;
6320 warning_list << "===== Broken Relative Combo Groups =====\n";
6321 }
6322 bool comma = false;
6323 warning_list << "In(";
6324 for(int c : in_set)
6325 {
6326 if(comma)
6327 warning_list << ",";
6328 else comma = true;
6329 warning_list << c;
6330 }
6331 warning_list << "),Out(";
6332 comma = false;
6333 for(int c : out_set)
6334 {
6335 if(comma)
6336 warning_list << ",";
6337 else comma = true;
6338 warning_list << c;
6339 }
6340 warning_list << ")\n";
6341 it = subset.erase(it);
6342 }
6343 }
6344 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Combo Warning");
6345
6346 processed_combos.clear();
6347 warning_flood = false;
6348 warning_list.clear();
6349
6350 return ret;
6351 }
6352
6353 void ComboMoveList::add_diff(int diff)
6354 {
6355 for(auto& ref : move_refs)
6356 ref->addCombo(diff);
6357 }
6358
6359 static void collect_subscreen_tiles(SubscrWidget& widget, TileMoveList& list)
6360 {
6361 if (auto w = dynamic_cast<SW_2x2Frame*>(&widget))
6362 {
6363 list.add_tile(&w->tile, 2, 2, "2x2 Frame");
6364 }
6365 else if (auto w = dynamic_cast<SW_TriFrame*>(&widget))
6366 {
6367 list.add_tile(&w->frame_tile, 6, 3, "McGuffin Frame - Frame");
6368 list.add_tile(&w->piece_tile, "McGuffin Frame - Piece");
6369 }
6370 else if (auto w = dynamic_cast<SW_McGuffin*>(&widget))
6371 {
6372 list.add_tile(&w->tile, "McGuffin Piece");
6373 }
6374 else if (auto w = dynamic_cast<SW_TileBlock*>(&widget))
6375 {
6376 list.add_tile(&w->tile, w->w, w->h, "TileBlock");
6377 }
6378 else if (auto w = dynamic_cast<SW_MiniTile*>(&widget))
6379 {
6380 if (w->tile == -1)
6381 return;
6382
6383 list.add_tile(&w->tile, "MiniTile");
6384 }
6385 else if (auto w = dynamic_cast<SW_GaugePiece*>(&widget))
6386 {
6387 int fr = w->frames ? w->frames : 1;
6388 fr = fr * (1+(w->get_per_container()/(w->unit_per_frame+1)));
6389 if(!(w->flags&SUBSCR_GAUGE_FULLTILE))
6390 fr = (fr/4_zf).getCeil();
6391
6392 for(auto q = 0; q < 4; ++q)
6393 {
6394 list.add_tile(&w->mts[q].mt_tile, fr, 1, fmt::format("Gauge Tile {}", q));
6395 }
6396 }
6397 }
6398
6399 static void collect_subscreen_tiles(SubscrPage& page, TileMoveList& list)
6400 {
6401 for(auto q = 0; q < page.contents.size(); ++q)
6402 {
6403 size_t indx = list.move_refs.size();
6404 collect_subscreen_tiles(*page.contents[q], list);
6405 for(; indx < list.move_refs.size(); ++indx)
6406 {
6407 auto& ref = list.move_refs[indx];
6408 ref->name = fmt::format("Widget {} - {}", q, ref->name);
6409 }
6410 }
6411 }
6412
6413 static void collect_subscreen_tiles(ZCSubscreen& subscreen, TileMoveList& list)
6414 {
6415 for (auto q = 0; q < subscreen.pages.size(); ++q)
6416 {
6417 size_t indx = list.move_refs.size();
6418 collect_subscreen_tiles(subscreen.pages[q], list);
6419 for(; indx < list.move_refs.size(); ++indx)
6420 {
6421 auto& ref = list.move_refs[indx];
6422 ref->name = fmt::format("Page {} - {}", q, ref->name);
6423 }
6424 }
6425 }
6426
6427 bool _handle_tile_move(TileMoveProcess dest_process, optional<TileMoveProcess> source_process, int diff, TileMoveUndo* on_undo = nullptr, std::function<void(int32_t)> every_proc = nullptr, TileMoveList::Mode mode = TileMoveList::Mode::MOVE)
6428 {
6429 bool BSZ2 = get_qr(qr_BSZELDA);
6430 bool move = source_process.has_value();
6431 TileMoveUndo local_undo;
6432 TileMoveUndo& storage = on_undo ? *on_undo : local_undo;
6433 auto& vec = storage.vec;
6434 storage.diff = diff;
6435 storage.state = false;
6436
6437 //Combos
6438 {
6439 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6440 dest_process, source_process, mode,
6441 move
6442 ? "The tiles used by the following combos will be partially cleared by the move."
6443 : "The tiles used by the following combos will be partially or completely overwritten by this process."
6444 ));
6445 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6446 {
6447 auto& cmb = combobuf[q];
6448 auto lbl = fmt::format("Combo {}{}", q, cmb.label.empty() ? ""
6449 : fmt::format(" ({})", cmb.label));
6450 movelist->add_combo(&cmb, lbl);
6451
6452 //type-specific
6453 char const* type_name = ZI.getComboTypeName(cmb.type);
6454 switch(cmb.type)
6455 {
6456 case cSPOTLIGHT:
6457 {
6458 if(!(cmb.usrflags & cflag1))
6459 break;
6460 movelist->add_tile_10k(&cmb.attributes[0], 16, 1, fmt::format("{} - Type '{}' - Beam Tiles", lbl, type_name));
6461 break;
6462 }
6463 }
6464 }
6465 if(!every_proc && !movelist->check_prot())
6466 return false;
6467 }
6468 //Items
6469 {
6470 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6471 dest_process, source_process, mode,
6472 move
6473 ? "The tiles used by the following items will be partially cleared by the move."
6474 : "The tiles used by the following items will be partially or completely overwritten by this process."
6475 ));
6476 build_bii_list(false);
6477 for(int32_t u=0; u<MAXITEMS; u++)
6478 {
6479 auto id = bii[u].i;
6480 itemdata& itm = itemsbuf[id];
6481 if(itm.family == itype_bottle)
6482 {
6483 vector<std::tuple<int,int,int>> rects;
6484 auto fr = itm.frames;
6485 for(int q = 0; q < NUM_BOTTLE_TYPES; ++q)
6486 {
6487 bottletype const& bt = QMisc.bottle_types[q];
6488 if(bt.is_blank())
6489 continue;
6490 rects.emplace_back(fr+q*fr, fr, 1);
6491 }
6492 movelist->add_tile(&itm.tile, fr, 1, fmt::format("Item {}", id),
6493 false, 0, 0, rects);
6494 }
6495 else movelist->add_tile(&itm.tile, itm.frames, 1, fmt::format("Item {}", id));
6496 }
6497 if(!every_proc && !movelist->check_prot())
6498 return false;
6499 }
6500 //Weapon sprites
6501 {
6502 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6503 dest_process, source_process, mode,
6504 move
6505 ? "The tiles used by the following weapons will be partially cleared by the move."
6506 : "The tiles used by the following weapons will be partially or completely overwritten by this process."
6507 ));
6508 build_biw_list();
6509
6510 for(int32_t u=0; u<MAXWPNS; u++)
6511 {
6512 bool ignore_frames=false;
6513 int32_t m=0;
6514
6515 auto id = biw[u].i;
6516 auto& wpn = wpnsbuf[id];
6517
6518 switch(biw[u].i)
6519 {
6520 case wSWORD:
6521 case wWSWORD:
6522 case wMSWORD:
6523 case wXSWORD:
6524 m=3+((wpnsbuf[biw[u].i].type==3)?1:0);
6525 break;
6526
6527 case wSWORDSLASH:
6528 case wWSWORDSLASH:
6529 case wMSWORDSLASH:
6530 case wXSWORDSLASH:
6531 m=4;
6532 break;
6533
6534 case iwMMeter:
6535 m=9;
6536 break;
6537
6538 case wBRANG:
6539 case wMBRANG:
6540 case wFBRANG:
6541 m=BSZ2?1:3;
6542 break;
6543
6544 case wBOOM:
6545 case wSBOOM:
6546 case ewBOOM:
6547 case ewSBOOM:
6548 ignore_frames=true;
6549 m=2;
6550 break;
6551
6552 case wWAND:
6553 m=1;
6554 break;
6555
6556 case wMAGIC:
6557 m=1;
6558 break;
6559
6560 case wARROW:
6561 case wSARROW:
6562 case wGARROW:
6563 case ewARROW:
6564 m=1;
6565 break;
6566
6567 case wHAMMER:
6568 m=8;
6569 break;
6570
6571 case wHSHEAD:
6572 m=1;
6573 break;
6574
6575 case wHSCHAIN_H:
6576 m=1;
6577 break;
6578
6579 case wHSCHAIN_V:
6580 m=1;
6581 break;
6582
6583 case wHSHANDLE:
6584 m=1;
6585 break;
6586
6587 case iwDeath:
6588 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6589 {
6590 ignore_frames = true;
6591 m=BSZ2?4:2;
6592 }
6593 break;
6594
6595 case iwSpawn:
6596 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6597 {
6598 ignore_frames = true;
6599 m=3;
6600 }
6601 break;
6602 }
6603
6604 movelist->add_tile(&wpn.tile, zc_max((ignore_frames?0:wpn.frames),1)+m,
6605 1, fmt::format("{} {}", biw[u].s, id));
6606
6607 //Tile 54+55 are "Impact (not shown in sprite list)", for u==3 "Arrow" and u==9 "Boomerang"
6608 //...these can't be updated by a move.
6609 if((u==3)||(u==9))
6610 {
6611 static int32_t impact_tiles[2] = {54,54};
6612 auto& tile = impact_tiles[u==3 ? 0 : 1];
6613 tile = 54; //dummy tile, ensure it's correct
6614 movelist->add_tile(&tile, 2, 1,
6615 fmt::format("{} Impact (not shown in sprite list)",(u==3)?"Arrow":"Boomerang"),
6616 true);
6617 }
6618 }
6619 if(!every_proc && !movelist->check_prot())
6620 return false;
6621 }
6622 //Player sprites
6623 {
6624 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6625 dest_process, source_process, mode,
6626 move
6627 ? "The tiles used by the following player sprites will be partially cleared by the move."
6628 : "The tiles used by the following player sprites will be partially or completely overwritten by this process."
6629 ));
6630 {
6631 int32_t a_style=(zinit.heroAnimationStyle);
6632 #define ADD_PLAYER_SPRITE(ref_sprite, frames, name) \
6633 do \
6634 { \
6635 movelist->add_tile(&ref_sprite[spr_tile], \
6636 (ref_sprite[spr_extend] < 2 ? 1 : 2) * frames, \
6637 ref_sprite[spr_extend] < 1 ? 1 : 2, \
6638 name, false, \
6639 ref_sprite[spr_extend] < 2 ? 0 : -1, \
6640 ref_sprite[spr_extend] < 1 ? 0 : -1); \
6641 } while(false)
6642 // + (ref_sprite[spr_extend] < 2 ? 0 : 1) //this was on some of the 'width's before... but doesn't make sense?
6643
6644 for(int32_t i=0; i<4; ++i)
6645 {
6646 ADD_PLAYER_SPRITE(walkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Walking ({})", dirstr_proper[i]));
6647 }
6648
6649 for(int32_t i=0; i<4; ++i)
6650 {
6651 ADD_PLAYER_SPRITE(slashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slashing ({})", dirstr_proper[i]));
6652 }
6653
6654 for(int32_t i=0; i<4; ++i)
6655 {
6656 ADD_PLAYER_SPRITE(stabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Stabbing ({})", dirstr_proper[i]));
6657 }
6658
6659 for(int32_t i=0; i<4; ++i)
6660 {
6661 ADD_PLAYER_SPRITE(poundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Pounding ({})", dirstr_proper[i]));
6662 }
6663
6664 for(int32_t i=0; i<2; ++i)
6665 {
6666 ADD_PLAYER_SPRITE(holdspr[0][i], 1, fmt::format("Hold (Land, {}-hand)", i+1));
6667 }
6668
6669 ADD_PLAYER_SPRITE(castingspr, 1, "Casting");
6670
6671 for(int32_t i=0; i<4; ++i)
6672 {
6673 ADD_PLAYER_SPRITE(floatspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Floating ({})", dirstr_proper[i]));
6674 }
6675
6676 for(int32_t i=0; i<4; ++i)
6677 {
6678 ADD_PLAYER_SPRITE(swimspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Swimming ({})", dirstr_proper[i]));
6679 }
6680
6681 for(int32_t i=0; i<4; ++i)
6682 {
6683 ADD_PLAYER_SPRITE(divespr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Diving ({})", dirstr_proper[i]));
6684 }
6685
6686 for(int32_t i=0; i<2; ++i)
6687 {
6688 ADD_PLAYER_SPRITE(holdspr[1][i], 1, fmt::format("Hold (Water, {}-hand)", i));
6689 }
6690
6691 for(int32_t i=0; i<4; ++i)
6692 {
6693 ADD_PLAYER_SPRITE(jumpspr[i], 3, fmt::format("Jumping ({})", dirstr_proper[i]));
6694 }
6695
6696 for(int32_t i=0; i<4; ++i)
6697 {
6698 ADD_PLAYER_SPRITE(chargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Charging ({})", dirstr_proper[i]));
6699 }
6700 for(int32_t i=0; i<4; ++i)
6701 {
6702 ADD_PLAYER_SPRITE(revslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slash 2 ({})", dirstr_proper[i]));
6703 }
6704 for(int32_t i=0; i<4; ++i)
6705 {
6706 ADD_PLAYER_SPRITE(fallingspr[i], 7, fmt::format("Falling ({})", dirstr_proper[i]));
6707 }
6708 for(int32_t i=0; i<4; ++i)
6709 {
6710 ADD_PLAYER_SPRITE(liftingspr[i], liftingspr[i][spr_frames], fmt::format("Lifting ({})", dirstr_proper[i]));
6711 }
6712 for(int32_t i=0; i<4; ++i)
6713 {
6714 ADD_PLAYER_SPRITE(liftingwalkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Lift-Walking ({})", dirstr_proper[i]));
6715 }
6716 for(int32_t i=0; i<4; ++i)
6717 {
6718 ADD_PLAYER_SPRITE(drowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Drowning ({})", dirstr_proper[i]));
6719 }
6720 for(int32_t i=0; i<4; ++i)
6721 {
6722 ADD_PLAYER_SPRITE(drowning_lavaspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Lava Drowning ({})", dirstr_proper[i]));
6723 }
6724 for(int32_t i=0; i<4; ++i)
6725 {
6726 ADD_PLAYER_SPRITE(sideswimspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swimming ({})", dirstr_proper[i]));
6727 }
6728 //69
6729 for(int32_t i=0; i<4; ++i)
6730 {
6731 ADD_PLAYER_SPRITE(sideswimslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Side-Swim Slash ({})", dirstr_proper[i]));
6732 }
6733 //73
6734 for(int32_t i=0; i<4; ++i)
6735 {
6736 ADD_PLAYER_SPRITE(sideswimstabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Stab ({})", dirstr_proper[i]));
6737 }
6738 //77
6739 for(int32_t i=0; i<4; ++i)
6740 {
6741 ADD_PLAYER_SPRITE(sideswimpoundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Pound ({})", dirstr_proper[i]));
6742 }
6743 //81
6744 for(int32_t i=0; i<4; ++i)
6745 {
6746 ADD_PLAYER_SPRITE(sideswimchargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Side-Swim Charging ({})", dirstr_proper[i]));
6747 }
6748 //85
6749 ADD_PLAYER_SPRITE(sideswimholdspr[spr_hold1], 1, "Hold (Side-Water, 1-hand)");
6750 ADD_PLAYER_SPRITE(sideswimholdspr[spr_hold2], 1, "Hold (Side-Water, 2-hand)");
6751 ADD_PLAYER_SPRITE(sideswimcastingspr, 1, "Side-Swim Casting");
6752 for(int32_t i=0; i<4; ++i)
6753 {
6754 ADD_PLAYER_SPRITE(sidedrowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swim Drowning ({})", dirstr_proper[i]));
6755 }
6756 //91
6757 }
6758 if(!every_proc && !movelist->check_prot())
6759 return false;
6760 }
6761 //Map Styles
6762 {
6763 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6764 dest_process, source_process, mode,
6765 move
6766 ? "The tiles used by the following map styles will be partially cleared by the move."
6767 : "The tiles used by the following map styles will be partially or completely overwritten by this process."
6768 ));
6769 movelist->add_tile(&QMisc.colors.blueframe_tile, 2, 2, "Frame");
6770 movelist->add_tile(&QMisc.colors.HCpieces_tile, zinit.hcp_per_hc, 1, "Heart Container Piece");
6771 movelist->add_tile(&QMisc.colors.triforce_tile, BSZ2?2:1, BSZ2?3:1, "McGuffin Fragment");
6772 movelist->add_tile(&QMisc.colors.triframe_tile, BSZ2?7:6, BSZ2?7:3, "McGuffin Frame");
6773 movelist->add_tile(&QMisc.colors.overworld_map_tile, 5, 3, "Overworld Map");
6774 movelist->add_tile(&QMisc.colors.dungeon_map_tile, 5, 3, "Dungeon Map");
6775 if(!every_proc && !movelist->check_prot())
6776 return false;
6777 }
6778 //Game Icons
6779 {
6780 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6781 dest_process, source_process, mode,
6782 move
6783 ? "The tiles used by the following game icons will be partially cleared by the move."
6784 : "The tiles used by the following game icons will be partially or completely overwritten by this process."
6785 ));
6786 for(int32_t u=0; u<4; u++)
6787 movelist->add_tile(&QMisc.icons[u], fmt::format("Game Icon {}", u));
6788 if(!every_proc && !movelist->check_prot())
6789 return false;
6790 }
6791 //DMaps
6792 {
6793 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6794 dest_process, source_process, mode,
6795 move
6796 ? "The tiles used by the following dmaps will be partially cleared by the move."
6797 : "The tiles used by the following dmaps will be partially or completely overwritten by this process."
6798 ));
6799 for(int32_t u=0; u<MAXDMAPS; u++)
6800 {
6801 auto& dm = DMaps[u];
6802 movelist->add_tile(&dm.minimap_1_tile, 5, 3, fmt::format("DMap {} - Minimap (Empty)", u));
6803 movelist->add_tile(&dm.minimap_2_tile, 5, 3, fmt::format("DMap {} - Minimap (Filled)", u));
6804 movelist->add_tile(&dm.largemap_1_tile, BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Empty)", u));
6805 movelist->add_tile(&dm.largemap_2_tile, BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Filled)", u));
6806 }
6807 if(!every_proc && !movelist->check_prot())
6808 return false;
6809 }
6810 //Enemies
6811 {
6812 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6813 dest_process, source_process, mode,
6814 move
6815 ? "The tiles used by the following enemies will be partially cleared by the move."
6816 : "The tiles used by the following enemies will be partially or completely overwritten by this process."
6817 ));
6818 build_bie_list(false);
6819 bool newtiles=get_qr(qr_NEWENEMYTILES)!=0;
6820 for(int u=0; u<eMAXGUYS; u++)
6821 {
6822 guydata& enemy=guysbuf[bie[u].i];
6823 bool darknut=false;
6824 int32_t gleeok=0;
6825
6826 if(enemy.family==eeWALK && ((enemy.flags&(guy_shield_back|guy_shield_front|guy_shield_left|guy_shield_right))!=0))
6827 darknut=true;
6828 else if(enemy.family==eeGLEEOK)
6829 {
6830 // Not certain this is the right thing to check...
6831 if(enemy.attributes[2] == 0)
6832 gleeok=1;
6833 else
6834 gleeok=2;
6835 }
6836
6837 // Dummied out enemies
6838 if(bie[u].i>=eOCTO1S && bie[u].i<e177)
6839 {
6840 if(old_guy_string[bie[u].i][strlen(old_guy_string[bie[u].i])-1]==' ')
6841 {
6842 continue;
6843 }
6844 }
6845
6846 if(newtiles)
6847 {
6848 if(guysbuf[bie[u].i].e_tile==0)
6849 {
6850 continue;
6851 }
6852
6853 vector<std::tuple<int,int,int>> rects;
6854
6855 if(darknut)
6856 {
6857 rects.emplace_back(enemy.e_tile+6*TILES_PER_ROW, enemy.e_width, enemy.e_height);
6858 }
6859 else if(enemy.family==eeGANON)
6860 {
6861 rects.emplace_back(enemy.e_tile+2*TILES_PER_ROW, 20, 4);
6862 }
6863 else if(gleeok) //No idea if this is actually *RIGHT*, but I copied what was here before faithfully -Em
6864 {
6865 for(int32_t j=0; j<4; ++j)
6866 {
6867 rects.emplace_back(
6868 TILECOL(guysbuf[bie[u].i].e_tile+(gleeok>1?-4:8)) + TILES_PER_ROW*TILEROW(guysbuf[bie[u].i].e_tile+8)+(j<<1)+(gleeok>1?1:0),
6869 4, 1);
6870 }
6871 int32_t c=TILECOL(guysbuf[bie[u].i].e_tile)+(gleeok>1?-12:0);
6872 int32_t r=TILEROW(guysbuf[bie[u].i].e_tile)+(gleeok>1?17:8);
6873 rects.emplace_back(c+TILES_PER_ROW*r, 20, 3);
6874 rects.emplace_back(c+TILES_PER_ROW*(r+3), 16, 6);
6875 }
6876 movelist->add_tile(&enemy.e_tile, enemy.e_width, enemy.e_height, fmt::format("Enemy {} ({}) 'New'", u, bie[u].s),
6877 false, 0, 0, rects);
6878 }
6879 else
6880 {
6881 if(guysbuf[bie[u].i].tile==0)
6882 {
6883 continue;
6884 }
6885 movelist->add_tile(&enemy.tile, enemy.width, enemy.height, fmt::format("Enemy {} ({}) 'Old'", u, bie[u].s));
6886
6887 if(guysbuf[bie[u].i].s_tile!=0)
6888 {
6889 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6890 }
6891 }
6892 }
6893 if(!every_proc && !movelist->check_prot())
6894 return false;
6895 }
6896 //Subscreens
6897 {
6898 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6899 dest_process, source_process, mode,
6900 move
6901 ? "The tiles used by the following subscreen widgets will be partially cleared by the move."
6902 : "The tiles used by the following subscreen widgets will be partially or completely overwritten by this process."
6903 ));
6904
6905 for(auto q = 0; q < subscreens_active.size(); ++q)
6906 {
6907 size_t indx = movelist->move_refs.size();
6908 collect_subscreen_tiles(subscreens_active[q], *movelist.get());
6909 for(; indx < movelist->move_refs.size(); ++indx)
6910 {
6911 auto& ref = movelist->move_refs[indx];
6912 ref->name = fmt::format("Active Subscr {} - {}", q, ref->name);
6913 }
6914 }
6915 for(auto q = 0; q < subscreens_passive.size(); ++q)
6916 {
6917 size_t indx = movelist->move_refs.size();
6918 collect_subscreen_tiles(subscreens_passive[q], *movelist.get());
6919 for(; indx < movelist->move_refs.size(); ++indx)
6920 {
6921 auto& ref = movelist->move_refs[indx];
6922 ref->name = fmt::format("Passive Subscr {} - {}", q, ref->name);
6923 }
6924 }
6925 for(auto q = 0; q < subscreens_overlay.size(); ++q)
6926 {
6927 size_t indx = movelist->move_refs.size();
6928 collect_subscreen_tiles(subscreens_overlay[q], *movelist.get());
6929 for(; indx < movelist->move_refs.size(); ++indx)
6930 {
6931 auto& ref = movelist->move_refs[indx];
6932 ref->name = fmt::format("Overlay Subscr {} - {}", q, ref->name);
6933 }
6934 }
6935 if(!every_proc && !movelist->check_prot())
6936 return false;
6937 }
6938 //Strings
6939 {
6940 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6941 dest_process, source_process, mode,
6942 move
6943 ? "The tiles used by the following strings will be partially cleared by the move."
6944 : "The tiles used by the following strings will be partially or completely overwritten by this process."
6945 ));
6946 for(size_t q = 0; q < msg_count; ++q)
6947 {
6948 MsgStr& str = MsgStrings[q];
6949 bool fulltile = str.stringflags & STRINGFLAG_FULLTILE;
6950 movelist->add_tile(&str.tile, fulltile ? (str.w/16_zf).getCeil() : 2,
6951 fulltile ? (str.h/16_zf).getCeil() : 2, fmt::format("{} (BG): '{}'", q, util::snip(str.s,100)));
6952 movelist->add_tile(&str.portrait_tile, str.portrait_tw, str.portrait_th,
6953 fmt::format("{} (Port.): '{}'", q, util::snip(str.s,100)));
6954 }
6955 if(!every_proc && !movelist->check_prot())
6956 return false;
6957 }
6958
6959 if(source_process) //Apply the 'diff' value to all moved tiles
6960 storage.redo();
6961 if(every_proc)
6962 for(auto &list : vec)
6963 for(auto &ref : list->move_refs)
6964 ref->forEach(every_proc);
6965 return true;
6966 }
6967 bool handle_tile_move(TileMoveProcess dest_process)
6968 {
6969 return _handle_tile_move(dest_process, nullopt, 0);
6970 }
6971 bool handle_tile_move(TileMoveProcess dest_process, TileMoveProcess source_process, int diff, TileMoveUndo& on_undo)
6972 {
6973 return _handle_tile_move(dest_process, source_process, diff, &on_undo);
6974 }
6975 void for_every_used_tile(std::function<void(int32_t)> proc)
6976 {
6977 reset_combo_animations();
6978 reset_combo_animations2();
6979 TileMoveProcess all_tiles {.rect = false, ._first = 0, ._last = NEWMAXTILES-1};
6980 _handle_tile_move(all_tiles, nullopt, 0, nullptr, proc, TileMoveList::Mode::CHECK_ALL);
6981 }
6982
6983 bool _handle_combo_move(ComboMoveProcess dest_process, optional<ComboMoveProcess> source_process, int diff, ComboMoveUndo* on_undo)
6984 {
6985 bool BSZ2 = get_qr(qr_BSZELDA);
6986 bool move = source_process.has_value();
6987 ComboMoveUndo local_undo;
6988 ComboMoveUndo& storage = on_undo ? *on_undo : local_undo;
6989 auto& vec = storage.vec;
6990 auto& combo_links = storage.combo_links;
6991 storage.diff = diff;
6992 storage.state = false;
6993 //Combo relative links
6994 {
6995 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6996 {
6997 newcombo& cmb = combobuf[q];
6998 if(cmb.trigchange)
6999 combo_links.add_to(q, q+cmb.trigchange);
7000 bool next = cmb.flag == mfSECRETSNEXT;
7001 switch(cmb.type)
7002 {
7003 case cPOUND:
7004 case cLOCKBLOCK: case cLOCKBLOCK2:
7005 case cBOSSLOCKBLOCK: case cBOSSLOCKBLOCK2:
7006 case cCHEST: case cCHEST2:
7007 case cLOCKEDCHEST: case cLOCKEDCHEST2:
7008 case cBOSSCHEST: case cBOSSCHEST2:
7009 case cSTEP: case cSTEPSAME: case cSTEPALL: case cSTEPCOPY:
7010 case cSLASHNEXT: case cSLASHNEXTITEM: case cBUSHNEXT:
7011 case cSLASHNEXTTOUCHY: case cSLASHNEXTITEMTOUCHY: case cBUSHNEXTTOUCHY:
7012 case cTALLGRASSNEXT: case cCRUMBLE:
7013 next = true;
7014 break;
7015 case cCSWITCH: case cCSWITCHBLOCK:
7016 combo_links.add_to(q, q+cmb.attributes[0]);
7017 break;
7018 case cLIGHTTARGET:
7019 if(cmb.usrflags & cflag1)
7020 combo_links.add_to(q, q-1);
7021 else next = true;
7022 break;
7023 case cSTEPSFX:
7024 if((cmb.usrflags&(cflag1|cflag3)) == cflag1)
7025 next = true;
7026 break;
7027 }
7028 if(next)
7029 combo_links.add_to(q, q+1);
7030 }
7031 }
7032
7033 //This function is expensive! Any optimizations possible should be made. -Em
7034
7035 //OPT: Check for a 0-val preemptively, to avoid processing the fmt::format strings
7036 #define ADDC(ptr, str) \
7037 if(*ptr) movelist->add_combo(ptr, ComboProtection ? str : "");
7038 #define ADDC_10k(ptr, str) \
7039 if(*ptr) movelist->add_combo_10k(ptr, ComboProtection ? str : "");
7040 //Combos
7041 {
7042 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7043 combo_links, dest_process, source_process,
7044 move
7045 ? "The combos used by the following combos will be partially cleared by the move."
7046 : "The combos used by the following combos will be partially or completely overwritten by this process."
7047 ));
7048 for(int32_t q = 0; q < MAXCOMBOS; ++q)
7049 {
7050 newcombo& cmb = combobuf[q];
7051 auto lbl = fmt::format("{}{}", q, cmb.label.empty() ? ""
7052 : fmt::format(" ({})", cmb.label));
7053 ADDC(&cmb.nextcombo, fmt::format("{} - Combo Cycle", lbl));
7054 ADDC(&cmb.liftcmb, fmt::format("{} - Lift Combo", lbl));
7055 ADDC(&cmb.liftundercmb, fmt::format("{} - Lift Undercombo", lbl));
7056 ADDC(&cmb.prompt_cid, fmt::format("{} - Triggers ButtonPrompt", lbl));
7057
7058 //type-specific
7059 char const* type_name = ZI.getComboTypeName(cmb.type);
7060 switch(cmb.type)
7061 {
7062 case cLOCKEDCHEST: case cBOSSCHEST:
7063 if(cmb.usrflags & cflag13)
7064 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7065 [[fallthrough]];
7066 case cCHEST:
7067 if(cmb.usrflags & cflag13)
7068 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7069 break;
7070 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
7071 if(cmb.usrflags & cflag13)
7072 {
7073 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7074 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7075 }
7076 break;
7077 case cSIGNPOST:
7078 if(cmb.usrflags & cflag13)
7079 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7080 break;
7081 case cBUTTONPROMPT:
7082 if(cmb.usrflags & cflag13)
7083 ADDC_10k(&cmb.attributes[0], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7084 break;
7085 }
7086 }
7087
7088 if(!movelist->check_prot())
7089 return false;
7090 }
7091 //Door Combo Sets
7092 {
7093 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7094 combo_links, dest_process, source_process,
7095 move
7096 ? "The combos used by the following screens will be partially cleared by the move."
7097 : "The combos used by the following screens will be partially or completely overwritten by this process."
7098 ));
7099 static const char* door_names[9] = {
7100 "Wall", "Locked", "Shuttered", "Boss", "Bombed", "Open", "Unlocked", "Open Shuttered", "Open Boss"
7101 };
7102 for(int32_t i=0; i<MAXDOORCOMBOSETS; i++)
7103 {
7104 auto& dcs = DoorComboSets[i];
7105 for(int32_t j=0; j<9; j++)
7106 {
7107 if(j<4)
7108 {
7109 ADDC(&dcs.walkthroughcombo[j], fmt::format("{} ({}): Walk-Through {}", i, dcs.name, j));
7110
7111 if(j<3)
7112 {
7113 if(j<2)
7114 {
7115 ADDC(&dcs.bombdoorcombo_u[j], fmt::format("{} ({}): Unused? bombdoorcombo_u {}", i, dcs.name, j));
7116 ADDC(&dcs.bombdoorcombo_d[j], fmt::format("{} ({}): Unused? bombdoorcombo_d {}", i, dcs.name, j));
7117 }
7118 ADDC(&dcs.bombdoorcombo_l[j], fmt::format("{} ({}): Unused? bombdoorcombo_l {}", i, dcs.name, j));
7119 ADDC(&dcs.bombdoorcombo_r[j], fmt::format("{} ({}): Unused? bombdoorcombo_r {}", i, dcs.name, j));
7120 }
7121 }
7122
7123 for(int32_t k=0; k<6; k++)
7124 {
7125 if(k<4)
7126 {
7127 ADDC(&dcs.doorcombo_u[j][k], fmt::format("{} ({}): Top, {} #{}", i, dcs.name, door_names[j], k));
7128 ADDC(&dcs.doorcombo_d[j][k], fmt::format("{} ({}): Bottom, {} #{}", i, dcs.name, door_names[j], k));
7129 }
7130
7131 ADDC(&dcs.doorcombo_l[j][k], fmt::format("{} ({}): Left, {} #{}", i, dcs.name, door_names[j], k));
7132 ADDC(&dcs.doorcombo_r[j][k], fmt::format("{} ({}): Right, {} #{}", i, dcs.name, door_names[j], k));
7133 }
7134 }
7135 }
7136
7137 if(!movelist->check_prot())
7138 return false;
7139 }
7140 //Combo Pools
7141 {
7142 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7143 combo_links, dest_process, source_process,
7144 move
7145 ? "The combos used by the following combo pools will be partially cleared by the move."
7146 : "The combos used by the following combo pools will be partially or completely overwritten by this process."
7147 ));
7148 for(auto q = 0; q < MAXCOMBOPOOLS; ++q)
7149 {
7150 combo_pool& pool = combo_pools[q];
7151 int idx = 0;
7152 for(cpool_entry& cp : pool.combos)
7153 ADDC(&cp.cid, fmt::format("{} index {}", q, idx++));
7154 }
7155
7156 if(!movelist->check_prot())
7157 return false;
7158 }
7159 //Auto Combos
7160 {
7161 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7162 combo_links, dest_process, source_process,
7163 move
7164 ? "The combos used by the following autocombos will be partially cleared by the move."
7165 : "The combos used by the following autocombos will be partially or completely overwritten by this process."
7166 ));
7167 for (auto q = 0; q < MAXAUTOCOMBOS; ++q)
7168 {
7169 combo_auto& cauto = combo_autos[q];
7170 int idx = 0;
7171 for (autocombo_entry& ac : cauto.combos)
7172 ADDC(&ac.cid, fmt::format("{} index {}", q, idx++));
7173 ADDC(&cauto.cid_erase, fmt::format("{} Erase Combo", q));
7174 ADDC(&cauto.cid_display, fmt::format("{} Display Combo", q));
7175 }
7176
7177 if(!movelist->check_prot())
7178 return false;
7179 }
7180 //Combo Aliases
7181 {
7182 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7183 combo_links, dest_process, source_process,
7184 move
7185 ? "The combos used by the following aliases will be partially cleared by the move."
7186 : "The combos used by the following aliases will be partially or completely overwritten by this process."
7187 ));
7188 for(int32_t i=0; i<MAXCOMBOALIASES; i++)
7189 {
7190 //dimensions are 1 less than you would expect -DD
7191 int32_t count=(comboa_lmasktotal(combo_aliases[i].layermask)+1)*(combo_aliases[i].width+1)*(combo_aliases[i].height+1);
7192
7193 for(int32_t j=0; j<count; j++)
7194 {
7195 ADDC(&combo_aliases[i].combos[j], fmt::format("{} index {}", i, j));
7196 }
7197 }
7198
7199 if(!movelist->check_prot())
7200 return false;
7201 }
7202 //Favorite Combos
7203 {
7204 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7205 combo_links, dest_process, source_process,
7206 move
7207 ? "The combos used by the following favorite combos will be partially cleared by the move."
7208 : "The combos used by the following favorite combos will be partially or completely overwritten by this process."
7209 ));
7210 for(int32_t i=0; i<MAXFAVORITECOMBOS; i++)
7211 {
7212 if(favorite_combo_modes[i] != dm_normal) //don't hit pools/aliases/autos, only combos!
7213 continue;
7214 ADDC(&favorite_combos[i], fmt::format("Favorite {}", i));
7215 }
7216
7217 if(!movelist->check_prot())
7218 return false;
7219 }
7220 //Bottle Shops
7221 {
7222 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7223 combo_links, dest_process, source_process,
7224 move
7225 ? "The combos used by the following bottle shops will be partially cleared by the move."
7226 : "The combos used by the following bottle shops will be partially or completely overwritten by this process."
7227 ));
7228 for(auto q = 0; q < 256; ++q)
7229 for(auto p = 0; p < 3; ++p)
7230 ADDC(&QMisc.bottle_shop_types[q].comb[p], fmt::format("{} slot {}", q, p));
7231
7232 if(!movelist->check_prot())
7233 return false;
7234 }
7235 //Screens //EXPENSIVE! DO THIS LAST!
7236 {
7237 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7238 combo_links, dest_process, source_process,
7239 move
7240 ? "The combos used by the following screens will be partially cleared by the move."
7241 : "The combos used by the following screens will be partially or completely overwritten by this process."
7242 ));
7243
7244 for(int32_t i=0; i<map_count && i<MAXMAPS; i++)
7245 {
7246 for(int32_t j=0; j<MAPSCRS; j++)
7247 {
7248 mapscr& scr = TheMaps[i*MAPSCRS+j];
7249
7250 if(!(scr.valid&mVALID))
7251 continue;
7252
7253 ADDC(&scr.undercombo, fmt::format("{}x{:02X} - UnderCombo", i, j));
7254
7255 // Specifying the exact position is too expensive - too much string creation.
7256 std::string data_str = ComboProtection ? fmt::format("{}x{:02X} - Combo", i, j) : "";
7257 for(int32_t k=0; k<176; k++)
7258 ADDC(&scr.data[k], data_str);
7259
7260 for(int32_t k=0; k<128; k++)
7261 ADDC(&scr.secretcombo[k], fmt::format("{}x{:02X} - SecretCombo {}", i, j, k));
7262
7263 word maxffc = scr.numFFC();
7264 for(word k=0; k<maxffc; k++)
7265 {
7266 ffcdata& ffc = scr.ffcs[k];
7267 ADDC(&ffc.data, fmt::format("{}x{:02X} - FFC {}", i, j, k+1));
7268 }
7269 }
7270 }
7271
7272 if(!movelist->check_prot())
7273 return false;
7274 }
7275 if(source_process) //Apply the 'diff' value to all moved combos
7276 storage.redo();
7277 return true;
7278 }
7279
7280 bool handle_combo_move(ComboMoveProcess dest_process)
7281 {
7282 return _handle_combo_move(dest_process, nullopt, 0, nullptr);
7283 }
7284 bool handle_combo_move(ComboMoveProcess dest_process, ComboMoveProcess source_process, int diff, ComboMoveUndo& on_undo)
7285 {
7286 return _handle_combo_move(dest_process, source_process, diff, &on_undo);
7287 }
7288 void register_used_tiles()
7289 {
7290 memset(used_tile_table, 0, sizeof(used_tile_table));
7291 for_every_used_tile([&](int tile)
7292 {
7293 used_tile_table[tile] = true;
7294 });
7295 }
7296
7297 bool overlay_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move, int32_t cs, bool backwards)
7298 {
7299 bool ctrl=(CHECK_CTRL_CMD);
7300 bool copied=false;
7301 copied=overlay_tiles_united(tile,tile2,copy,copycnt,rect_sel,move,cs,backwards);
7302
7303 if(copied)
7304 {
7305 saved=false;
7306 }
7307
7308 return copied;
7309 }
7310
7311 bool overlay_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move, int32_t cs, bool backwards)
7312 {
7313 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7314 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7315
7316 // if tile>tile2 then swap them
7317 if(tile>tile2)
7318 {
7319 zc_swap(tile, tile2);
7320 }
7321
7322 // alt=copy from right
7323 // shift=copy from bottom
7324
7325 int32_t copies=copycnt;
7326 int32_t dest_first=tile;
7327 int32_t dest_last=tile2;
7328 int32_t src_first=copy;
7329 int32_t src_last=copy+copies-1;
7330
7331 int32_t dest_top=0;
7332 int32_t dest_bottom=0;
7333 int32_t src_top=0;
7334 int32_t src_bottom=0;
7335 int32_t src_left=0, src_right=0;
7336 int32_t src_width=0, src_height=0;
7337 int32_t dest_left=0, dest_right=0;
7338 int32_t dest_width=0, dest_height=0;
7339 int32_t rows=0, cols=0;
7340
7341 if(rect)
7342 {
7343 dest_top=TILEROW(dest_first);
7344 dest_bottom=TILEROW(dest_last);
7345 src_top=TILEROW(src_first);
7346 src_bottom=TILEROW(src_last);
7347
7348 src_left= zc_min(TILECOL(src_first),TILECOL(src_last));
7349 src_right=zc_max(TILECOL(src_first),TILECOL(src_last));
7350 src_first=(src_top * TILES_PER_ROW)+src_left;
7351 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7352
7353 dest_left= zc_min(TILECOL(dest_first),TILECOL(dest_last));
7354 dest_right=zc_max(TILECOL(dest_first),TILECOL(dest_last));
7355 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7356 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7357
7358 //if no dest range set, then set one
7359 if((dest_first==dest_last)&&(src_first!=src_last))
7360 {
7361 if(alt)
7362 {
7363 dest_left=dest_right-(src_right-src_left);
7364 }
7365 else
7366 {
7367 dest_right=dest_left+(src_right-src_left);
7368 }
7369
7370 if(shift)
7371 {
7372 dest_top=dest_bottom-(src_bottom-src_top);
7373 }
7374 else
7375 {
7376 dest_bottom=dest_top+(src_bottom-src_top);
7377 }
7378
7379 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7380 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7381 }
7382 else
7383 {
7384 if(dest_right-dest_left<src_right-src_left) //destination is shorter than source
7385 {
7386 if(alt) //copy from right tile instead of left
7387 {
7388 src_left=src_right-(dest_right-dest_left);
7389 }
7390 else //copy from left tile
7391 {
7392 src_right=src_left+(dest_right-dest_left);
7393 }
7394 }
7395 else if(dest_right-dest_left>src_right-src_left) //destination is longer than source
7396 {
7397 if(alt) //copy from right tile instead of left
7398 {
7399 dest_left=dest_right-(src_right-src_left);
7400 }
7401 else //copy from left tile
7402 {
7403 dest_right=dest_left+(src_right-src_left);
7404 }
7405 }
7406
7407 if(dest_bottom-dest_top<src_bottom-src_top) //destination is shorter than source
7408 {
7409 if(shift) //copy from bottom tile instead of top
7410 {
7411 src_top=src_bottom-(dest_bottom-dest_top);
7412 }
7413 else //copy from top tile
7414 {
7415 src_bottom=src_top+(dest_bottom-dest_top);
7416 }
7417 }
7418 else if(dest_bottom-dest_top>src_bottom-src_top) //destination is longer than source
7419 {
7420 if(shift) //copy from bottom tile instead of top
7421 {
7422 dest_top=dest_bottom-(src_bottom-src_top);
7423 }
7424 else //copy from top tile
7425 {
7426 dest_bottom=dest_top+(src_bottom-src_top);
7427 }
7428 }
7429
7430 src_first=(src_top * TILES_PER_ROW)+src_left;
7431 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7432 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7433 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7434 }
7435
7436 cols=src_right-src_left+1;
7437 rows=src_bottom-src_top+1;
7438
7439 dest_width=dest_right-dest_left+1;
7440 dest_height=dest_bottom-dest_top+1;
7441 src_width=src_right-src_left+1;
7442 src_height=src_bottom-src_top+1;
7443
7444 }
7445 else //!rect
7446 {
7447 //if no dest range set, then set one
7448 if((dest_first==dest_last)&&(src_first!=src_last))
7449 {
7450 if(alt)
7451 {
7452 dest_first=dest_last-(src_last-src_first);
7453 }
7454 else
7455 {
7456 dest_last=dest_first+(src_last-src_first);
7457 }
7458 }
7459 else
7460 {
7461 if(dest_last-dest_first<src_last-src_first) //destination is shorter than source
7462 {
7463 if(alt) //copy from last tile instead of first
7464 {
7465 src_first=src_last-(dest_last-dest_first);
7466 }
7467 else //copy from first tile
7468 {
7469 src_last=src_first+(dest_last-dest_first);
7470 }
7471 }
7472 else if(dest_last-dest_first>src_last-src_first) //destination is longer than source
7473 {
7474 if(alt) //copy from last tile instead of first
7475 {
7476 dest_first=dest_last-(src_last-src_first);
7477 }
7478 else //copy from first tile
7479 {
7480 dest_last=dest_first+(src_last-src_first);
7481 }
7482 }
7483 }
7484
7485 copies=dest_last-dest_first+1;
7486 }
7487
7488
7489
7490 char buf2[80], buf3[80], buf4[80];
7491 sprintf(buf2, " ");
7492 sprintf(buf3, " ");
7493 sprintf(buf4, " ");
7494
7495 // warn if range extends beyond last tile
7496 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7497
7498 if(dest_last>=NEWMAXTILES)
7499 {
7500 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7501 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7502 return false;
7503 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7504 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7505 // {
7506 // return false;
7507 // }
7508 }
7509
7510
7511 TileMoveUndo on_undo;
7512 // Overwrite warnings
7513 TileMoveProcess dest{rect, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last};
7514 if(move)
7515 {
7516 TileMoveProcess src{rect, src_left, src_top, src_width, src_height, src_first, src_last};
7517 if(!handle_tile_move(dest, src, dest_first-src_first, on_undo))
7518 return false;
7519 }
7520 else
7521 {
7522 if(!handle_tile_move(dest))
7523 return false;
7524 }
7525 // copy tiles and delete if needed (move)
7526
7527 {
7528 go_tiles();
7529
7530 int32_t diff=dest_first-src_first;
7531
7532 if(rect)
7533 {
7534 for(int32_t r=0; r<rows; ++r)
7535 {
7536 for(int32_t c=0; c<cols; ++c)
7537 {
7538 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
7539 int32_t st=(src_first+((r*TILES_PER_ROW)+c));
7540
7541 if(dt>=NEWMAXTILES)
7542 continue;
7543
7544 overlay_tile(newtilebuf,dt,st,cs,backwards);
7545
7546 }
7547 }
7548 }
7549 else
7550 {
7551 for(int32_t c=0; c<copies; ++c)
7552 {
7553 int32_t dt=(dest_first+c);
7554 int32_t st=(src_first+c);
7555
7556 if(dt>=NEWMAXTILES)
7557 continue;
7558
7559 overlay_tile(newtilebuf,dt,st,cs,backwards);
7560
7561 if(move)
7562 {
7563 if(st<dest_first||st>(dest_first+c-1))
7564 reset_tile(newtilebuf, st, tf4Bit);
7565 }
7566 }
7567 }
7568 }
7569
7570 //now that tiles have moved, fix these buffers -DD
7571 register_blank_tiles();
7572 register_used_tiles();
7573
7574 if(move)
7575 last_tile_move_list = std::move(on_undo);
7576 return true;
7577 }
7578 //
7579 bool do_movetile_united(tile_move_data const& tmd)
7580 {
7581 char buf2[80], buf3[80], buf4[80];
7582 sprintf(buf2, " ");
7583 sprintf(buf3, " ");
7584 sprintf(buf4, " ");
7585
7586 // warn if range extends beyond last tile
7587 sprintf(buf4, "Some tiles will not be %s", tmd.move?"moved.":"copied.");
7588
7589 if(tmd.dest_last>=NEWMAXTILES)
7590 {
7591 sprintf(buf4, "%s operation cancelled.", tmd.move?"Move":"Copy");
7592 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7593 return false;
7594 }
7595
7596 TileMoveUndo on_undo;
7597 // Overwrite warnings
7598 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7599 if(tmd.move)
7600 {
7601 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7602 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7603 return false;
7604 }
7605 else
7606 {
7607 if(!handle_tile_move(dest))
7608 return false;
7609 }
7610
7611 // copy tiles and delete if needed (tmd.move)
7612 {
7613 go_tiles();
7614
7615 if(tmd.rect)
7616 {
7617 for(int32_t r=0; r<tmd.rows; ++r)
7618 {
7619 for(int32_t c=0; c<tmd.cols; ++c)
7620 {
7621 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7622 int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7623
7624 if(dt>=NEWMAXTILES)
7625 continue;
7626
7627 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7628
7629 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7630 {
7631 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7632 }
7633
7634 if(tmd.move)
7635 {
7636 if((st<tmd.dest_first||st>tmd.dest_first+((tmd.rows-1)*TILES_PER_ROW)+(tmd.cols-1)))
7637 reset_tile(newtilebuf, st, tf4Bit);
7638 else
7639 {
7640 int32_t destLeft=tmd.dest_first%TILES_PER_ROW;
7641 int32_t destRight=(tmd.dest_first+tmd.cols-1)%TILES_PER_ROW;
7642 if(destLeft<=destRight)
7643 {
7644 if(st%TILES_PER_ROW<destLeft || st%TILES_PER_ROW>destRight)
7645 reset_tile(newtilebuf, st, tf4Bit);
7646 }
7647 else // Wrapped around
7648 {
7649 if(st%TILES_PER_ROW<destLeft && st%TILES_PER_ROW>destRight)
7650 reset_tile(newtilebuf, st, tf4Bit);
7651 }
7652 }
7653 }
7654 }
7655 }
7656 }
7657 else
7658 {
7659 for(int32_t c=0; c<tmd.copies; ++c)
7660 {
7661 int32_t dt=(tmd.dest_first+c);
7662 int32_t st=(tmd.src_first+c);
7663
7664 if(dt>=NEWMAXTILES)
7665 continue;
7666
7667 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7668
7669 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7670 {
7671 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7672 }
7673
7674 if(tmd.move)
7675 {
7676 if(st<tmd.dest_first||st>(tmd.dest_first+c-1))
7677 reset_tile(newtilebuf, st, tf4Bit);
7678 }
7679 }
7680 }
7681 }
7682
7683 //now that tiles have moved, fix these buffers -DD
7684 register_blank_tiles();
7685 register_used_tiles();
7686
7687 if(tmd.move)
7688 last_tile_move_list = std::move(on_undo);
7689 return true;
7690 }
7691
7692 bool copy_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7693 {
7694 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7695 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7696
7697 // if tile>tile2 then swap them
7698 if(tile>tile2)
7699 {
7700 zc_swap(tile, tile2);
7701 }
7702
7703 // alt=copy from right
7704 // shift=copy from bottom
7705 tile_move_data tmd;
7706
7707 tmd.copies=copycnt;
7708 tmd.dest_first=tile;
7709 tmd.dest_last=tile2;
7710 tmd.src_first=copy;
7711 tmd.src_last=copy+tmd.copies-1;
7712 tmd.rect = rect;
7713 tmd.move = move;
7714
7715 if(rect)
7716 {
7717 tmd.dest_top=TILEROW(tmd.dest_first);
7718 tmd.dest_bottom=TILEROW(tmd.dest_last);
7719 tmd.src_top=TILEROW(tmd.src_first);
7720 tmd.src_bottom=TILEROW(tmd.src_last);
7721
7722 tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7723 tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7724 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7725 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7726
7727 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7728 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7729 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7730 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7731
7732 //if no dest range set, then set one
7733 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7734 {
7735 if(alt)
7736 {
7737 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7738 }
7739 else
7740 {
7741 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7742 }
7743
7744 if(shift)
7745 {
7746 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7747 }
7748 else
7749 {
7750 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7751 }
7752
7753 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7754 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7755 }
7756 else
7757 {
7758 if(tmd.dest_right-tmd.dest_left<tmd.src_right-tmd.src_left) //destination is shorter than source
7759 {
7760 if(alt) //copy from right tile instead of left
7761 {
7762 tmd.src_left=tmd.src_right-(tmd.dest_right-tmd.dest_left);
7763 }
7764 else //copy from left tile
7765 {
7766 tmd.src_right=tmd.src_left+(tmd.dest_right-tmd.dest_left);
7767 }
7768 }
7769 else if(tmd.dest_right-tmd.dest_left>tmd.src_right-tmd.src_left) //destination is longer than source
7770 {
7771 if(alt) //copy from right tile instead of left
7772 {
7773 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7774 }
7775 else //copy from left tile
7776 {
7777 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7778 }
7779 }
7780
7781 if(tmd.dest_bottom-tmd.dest_top<tmd.src_bottom-tmd.src_top) //destination is shorter than source
7782 {
7783 if(shift) //copy from bottom tile instead of top
7784 {
7785 tmd.src_top=tmd.src_bottom-(tmd.dest_bottom-tmd.dest_top);
7786 }
7787 else //copy from top tile
7788 {
7789 tmd.src_bottom=tmd.src_top+(tmd.dest_bottom-tmd.dest_top);
7790 }
7791 }
7792 else if(tmd.dest_bottom-tmd.dest_top>tmd.src_bottom-tmd.src_top) //destination is longer than source
7793 {
7794 if(shift) //copy from bottom tile instead of top
7795 {
7796 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7797 }
7798 else //copy from top tile
7799 {
7800 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7801 }
7802 }
7803
7804 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7805 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7806 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7807 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7808 }
7809
7810 tmd.cols=tmd.src_right-tmd.src_left+1;
7811 tmd.rows=tmd.src_bottom-tmd.src_top+1;
7812
7813 tmd.dest_width=tmd.dest_right-tmd.dest_left+1;
7814 tmd.dest_height=tmd.dest_bottom-tmd.dest_top+1;
7815 tmd.src_width=tmd.src_right-tmd.src_left+1;
7816 tmd.src_height=tmd.src_bottom-tmd.src_top+1;
7817
7818 }
7819 else //!rect
7820 {
7821 //if no dest range set, then set one
7822 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7823 {
7824 if(alt)
7825 {
7826 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7827 }
7828 else
7829 {
7830 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7831 }
7832 }
7833 else
7834 {
7835 if(tmd.dest_last-tmd.dest_first<tmd.src_last-tmd.src_first) //destination is shorter than source
7836 {
7837 if(alt) //copy from last tile instead of first
7838 {
7839 tmd.src_first=tmd.src_last-(tmd.dest_last-tmd.dest_first);
7840 }
7841 else //copy from first tile
7842 {
7843 tmd.src_last=tmd.src_first+(tmd.dest_last-tmd.dest_first);
7844 }
7845 }
7846 else if(tmd.dest_last-tmd.dest_first>tmd.src_last-tmd.src_first) //destination is longer than source
7847 {
7848 if(alt) //copy from last tile instead of first
7849 {
7850 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7851 }
7852 else //copy from first tile
7853 {
7854 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7855 }
7856 }
7857 }
7858
7859 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7860 }
7861
7862 return do_movetile_united(tmd);
7863 }
7864
7865 //
7866
7867 bool copy_tiles_united_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7868 {
7869 assert(!move); //not implemented
7870
7871 // if tile>tile2 then swap them
7872 if(tile>tile2)
7873 {
7874 zc_swap(tile, tile2);
7875 }
7876
7877 tile_move_data tmd;
7878 tmd.copies=copycnt;
7879 tmd.dest_first=tile;
7880 tmd.dest_last=tile2;
7881 tmd.src_first=copy;
7882 tmd.src_last=copy+tmd.copies-1;
7883
7884
7885
7886 if(rect)
7887 {
7888 tmd.dest_top=TILEROW(tmd.dest_first);
7889 tmd.dest_bottom=TILEROW(tmd.dest_last);
7890 //tmd.src_top=TILEROW(tmd.src_first);
7891 //tmd.src_bottom=TILEROW(tmd.src_last);
7892
7893 //tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7894 //tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7895 //tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7896 //tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7897
7898 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7899 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7900 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7901 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7902
7903
7904
7905
7906 tmd.dest_width=tmd.dest_right-tmd.dest_left;
7907 tmd.dest_height=tmd.dest_bottom-tmd.dest_top;
7908
7909 tmd.cols=tmd.dest_width+1;
7910 tmd.rows=tmd.dest_height+1;
7911
7912 al_trace("tmd.rows: %d\n", tmd.rows);
7913 al_trace("tmd.cols: %d\n", tmd.cols);
7914
7915
7916 }
7917 else //!rect
7918 {
7919 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7920 }
7921
7922
7923
7924 char buf2[80], buf3[80], buf4[80];
7925 sprintf(buf2, " ");
7926 sprintf(buf3, " ");
7927 sprintf(buf4, " ");
7928
7929 // warn if range extends beyond last tile
7930 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7931
7932 if(tmd.dest_last>=NEWMAXTILES)
7933 {
7934 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7935 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7936 return false;
7937 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7938 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7939 // {
7940 // return false;
7941 // }
7942 }
7943
7944 TileMoveUndo on_undo;
7945 // Overwrite warnings
7946 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7947 if(tmd.move)
7948 {
7949 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7950 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7951 return false;
7952 }
7953 else
7954 {
7955 if(!handle_tile_move(dest))
7956 return false;
7957 }
7958
7959 // copy tiles and delete if needed (move)
7960
7961 {
7962 go_tiles();
7963
7964 int32_t diff=tmd.dest_first-tmd.src_first;
7965
7966 if(rect)
7967 {
7968 al_trace("floodfill, rect\n");
7969 al_trace("tmd.rows: %d\n", tmd.rows);
7970 al_trace("tmd.cols: %d\n", tmd.cols);
7971 for(int32_t r=0; r<tmd.rows; ++r)
7972 {
7973 for(int32_t c=0; c<tmd.cols; ++c)
7974 {
7975 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7976 //int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7977
7978 if(dt>=NEWMAXTILES)
7979 continue;
7980
7981 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
7982
7983 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
7984 {
7985 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
7986 }
7987 }
7988 }
7989 }
7990 else
7991 {
7992 for(int32_t c=0; c<tmd.copies; ++c)
7993 {
7994 int32_t dt=(tmd.dest_first+c);
7995 int32_t st=(tmd.src_first+c);
7996
7997 if(dt>=NEWMAXTILES)
7998 continue;
7999
8000 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
8001
8002 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
8003 {
8004 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
8005 }
8006
8007 }
8008 }
8009 }
8010
8011 //now that tiles have moved, fix these buffers -DD
8012 register_blank_tiles();
8013 register_used_tiles();
8014
8015 if(tmd.move)
8016 last_tile_move_list = std::move(on_undo);
8017 return true;
8018 }
8019 //
8020
8021 bool copy_tiles_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
8022 {
8023 al_trace("Floodfill Psste\n");
8024 bool ctrl=(CHECK_CTRL_CMD);
8025 bool copied=false;
8026 copied=copy_tiles_united_floodfill(tile,tile2,copy,copycnt,rect_sel,move);
8027
8028 if(copied)
8029 {
8030 if(!ctrl)
8031 {
8032 copy=-1;
8033 tile2=tile;
8034 }
8035
8036 saved=false;
8037 }
8038
8039 return copied;
8040 }
8041
8042 bool copy_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
8043 {
8044 bool ctrl=(CHECK_CTRL_CMD);
8045 bool copied=false;
8046 copied=copy_tiles_united(tile,tile2,copy,copycnt,rect_sel,move);
8047
8048 if(copied)
8049 {
8050 if(!ctrl)
8051 {
8052 copy=-1;
8053 tile2=tile;
8054 }
8055
8056 saved=false;
8057 }
8058
8059 return copied;
8060 }
8061
8062 bool scale_or_rotate_tiles(int32_t &tile, int32_t &tile2, int32_t &cs, bool rotate)
8063 {
8064 // if tile>tile2 then swap them
8065 if(tile>tile2)
8066 {
8067 zc_swap(tile, tile2);
8068 }
8069 int32_t src_top = TILEROW(tile);
8070 int32_t src_bottom = TILEROW(tile2);
8071 int32_t src_left = zc_min(TILECOL(tile),TILECOL(tile2));
8072 int32_t src_right = zc_max(TILECOL(tile),TILECOL(tile2));
8073 int32_t src_first = (src_top * TILES_PER_ROW)+src_left;
8074 int32_t src_last = (src_bottom*TILES_PER_ROW)+src_right;
8075
8076 int32_t src_width = src_right-src_left+1,
8077 src_height = src_bottom-src_top+1;
8078 int32_t dest_width = src_width, dest_height = src_height;
8079 zfix dest_rot = 0_zf;
8080 if(rotate)
8081 RotateTileDialog(&dest_width, &dest_height, &dest_rot).show();
8082 else
8083 ScaleTileDialog(&dest_width, &dest_height).show();
8084 if (rotate)
8085 {
8086 if (dest_rot == 0) return false;
8087 }
8088 else
8089 {
8090 if (dest_width == src_width && dest_height == src_height) return false; //no scaling
8091 }
8092 dest_width = vbound(dest_width, 1, 20);
8093 dest_height = vbound(dest_height, 1, 20);
8094
8095 int32_t dest_top = src_top;
8096 int32_t dest_bottom = src_top+dest_height-1;
8097 int32_t dest_left = src_left;
8098 int32_t dest_right = src_left+dest_width-1;
8099 int32_t dest_first = src_first;
8100 int32_t dest_last = (dest_bottom*TILES_PER_ROW)+dest_right;
8101
8102
8103 if(dest_last>=NEWMAXTILES)
8104 {
8105 InfoDialog("Destination Error", "The destination extends beyond the last available tile row. Scale operation cancelled.").show();
8106 return false;
8107 }
8108
8109 // Overwrite warnings
8110 if(!handle_tile_move({true, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last}))
8111 return false;
8112
8113 //Do the rotate
8114 {
8115 go_tiles();
8116
8117 int32_t diff=dest_first-src_first;
8118 BITMAP *srcbmp = create_bitmap_ex(8,src_width*16,src_height*16),
8119 *destbmp = create_bitmap_ex(8,dest_width*16,dest_height*16);
8120 clear_bitmap(srcbmp); clear_bitmap(destbmp);
8121 overtileblock16(srcbmp, src_first, 0, 0, src_width, src_height, cs, 0);
8122 bool is8bit = newtilebuf[src_first].format == tf8Bit;
8123 if (rotate)
8124 {
8125 rotate_sprite(destbmp, srcbmp, 0, 0, ftofix(dest_rot * 0.7111111111111));
8126 }
8127 else
8128 {
8129 stretch_blit(srcbmp, destbmp, 0, 0, srcbmp->w, srcbmp->h,
8130 0, 0, destbmp->w, destbmp->h);
8131 }
8132 int32_t mhei = zc_max(src_height,dest_height),
8133 mwid = zc_max(src_width, dest_width);
8134 for(int32_t r=0; r<mhei; ++r)
8135 {
8136 for(int32_t c=0; c<mwid; ++c)
8137 {
8138 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
8139
8140 if(dt>=NEWMAXTILES)
8141 continue;
8142 if(r < dest_height && c < dest_width)
8143 {
8144 write_tile(newtilebuf, destbmp, dt, c*16, r*16, is8bit, false);
8145 }
8146 else reset_tile(newtilebuf, dt, tf4Bit);
8147 }
8148 }
8149 }
8150
8151 register_blank_tiles();
8152 register_used_tiles();
8153 return true;
8154 }
8155
8156 void copy_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool masscopy)
8157 {
8158 //these 2 shouldn't be needed, but just to be safe...
8159 reset_combo_animations();
8160 reset_combo_animations2();
8161
8162 if(tile2<tile)
8163 {
8164 zc_swap(tile,tile2);
8165 }
8166
8167 auto first = tile;
8168 auto last = masscopy ? tile2 : first + copycnt-1;
8169 if(!handle_combo_move({first,last}))
8170 return;
8171
8172 if(!masscopy)
8173 {
8174 if(tile==copy)
8175 {
8176 copy=-1;
8177 tile2=tile;
8178 return;
8179 }
8180
8181 // go_combos(); // commented because caller does it for us
8182 //if copying to an earlier combo, copy from left to right
8183 //otherwise, copy from right to left
8184 for(int32_t t=(tile<copy)?0:(copycnt-1); (tile<copy)?(t<copycnt):(t>=0); (tile<copy)?(t++):(t--))
8185 {
8186 if(tile+t < MAXCOMBOS)
8187 {
8188 combobuf[tile+t]=combobuf[copy+t];
8189 }
8190 }
8191
8192 copy=-1;
8193 tile2=tile;
8194 saved=false;
8195 }
8196 else
8197 {
8198 // go_combos();
8199 int32_t src=copy, dest=tile;
8200
8201 do
8202 {
8203 combobuf[dest]=combobuf[src];
8204 ++src;
8205 ++dest;
8206
8207 if((src-copy)==copycnt) src=copy;
8208 }
8209 while(dest<=tile2);
8210
8211 copy=-1;
8212 tile2=tile;
8213 saved=false;
8214 }
8215
8216 setup_combo_animations();
8217 setup_combo_animations2();
8218 }
8219
8220 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing)
8221 {
8222 reset_combo_animations();
8223 reset_combo_animations2();
8224 go_combos();
8225
8226 auto diff = cmd.tile - cmd.copy1;
8227 if(is_undoing)
8228 on_undo.undo();
8229 else if(!handle_combo_move({cmd.tile,cmd.tile+cmd.copycnt-1},{cmd.copy1,cmd.copy1+cmd.copycnt-1}, diff, on_undo))
8230 return false;
8231
8232 for(int32_t t=(cmd.tile<cmd.copy1)?0:(cmd.copycnt-1); (cmd.tile<cmd.copy1)?(t<cmd.copycnt):(t>=0); (cmd.tile<cmd.copy1)?(t++):(t--))
8233 {
8234 if(cmd.tile+t < MAXCOMBOS)
8235 {
8236 combobuf[cmd.tile+t]=combobuf[cmd.copy1+t];
8237 clear_combo(cmd.copy1+t);
8238 }
8239 }
8240
8241 setup_combo_animations();
8242 setup_combo_animations2();
8243 saved=false;
8244 return true;
8245 }
8246
8247 void move_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt)
8248 {
8249 if(tile2<tile)
8250 {
8251 zc_swap(tile,tile2);
8252 }
8253
8254 if(tile==copy)
8255 {
8256 copy=-1;
8257 tile2=tile;
8258 return;
8259 }
8260
8261 combo_move_data cmd;
8262 cmd.tile = tile;
8263 cmd.tile2 = tile2;
8264 cmd.copy1 = copy;
8265 cmd.copycnt = copycnt;
8266
8267 ComboMoveUndo on_undo;
8268 if(!do_movecombo(cmd, on_undo))
8269 return;
8270 last_combo_move_list = std::move(on_undo);
8271 copy=-1;
8272 tile2=tile;
8273 }
8274
8275 void do_delete_tiles(int32_t firsttile, int32_t lasttile, bool rect_sel)
8276 {
8277 if(firsttile > lasttile)
8278 zc_swap(firsttile,lasttile);
8279 int32_t coldiff = 0;
8280 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8281 {
8282 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8283 firsttile-=coldiff;
8284 lasttile+=coldiff;
8285 }
8286 for(int32_t t=firsttile; t<=lasttile; ++t)
8287 if(!rect_sel ||
8288 ((TILECOL(t)>=TILECOL(firsttile)) &&
8289 (TILECOL(t)<=TILECOL(lasttile))))
8290 reset_tile(newtilebuf, t, tf4Bit);
8291 saved=false;
8292 register_blank_tiles();
8293 }
8294
8295 void delete_tiles(int32_t &tile,int32_t &tile2,bool rect_sel)
8296 {
8297 char buf[40];
8298
8299 if(tile==tile2)
8300 {
8301 sprintf(buf,"Delete tile %d?",tile);
8302 }
8303 else
8304 {
8305 sprintf(buf,"Delete tiles %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
8306 }
8307
8308 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8309 {
8310 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8311
8312 go_tiles();
8313
8314 //if copying to an earlier tile, copy from left to right
8315 //otherwise, copy from right to left
8316 do_delete_tiles(firsttile, lasttile, rect_sel);
8317
8318 tile=tile2=zc_min(tile,tile2);
8319 saved=false;
8320 register_blank_tiles();
8321 }
8322 }
8323
8324 void overlay_tile2(int32_t dest,int32_t src,int32_t cs,bool backwards)
8325 {
8326 byte buf[256];
8327 go_tiles();
8328
8329 unpack_tile(newtilebuf, dest, 0, false);
8330
8331 for(int32_t i=0; i<256; i++)
8332 buf[i] = unpackbuf[i];
8333
8334 unpack_tile(newtilebuf, src, 0, false);
8335
8336 if(newtilebuf[src].format>tf4Bit)
8337 {
8338 cs=0;
8339 }
8340
8341 cs &= 15;
8342 cs <<= CSET_SHFT;
8343
8344 for(int32_t i=0; i<256; i++)
8345 {
8346 if(backwards)
8347 {
8348 if(!buf[i])
8349 {
8350 buf[i] = unpackbuf[i]+cs;
8351 }
8352 }
8353 else
8354 {
8355 if(unpackbuf[i])
8356 {
8357 buf[i] = unpackbuf[i]+cs;
8358 }
8359 }
8360 }
8361
8362 pack_tile(newtilebuf, buf,dest);
8363 saved=false;
8364 }
8365
8366 void mass_overlay_tile(int32_t dest1, int32_t dest2, int32_t src, int32_t cs, bool backwards, bool rect_sel)
8367 {
8368 //byte buf[256];
8369 go_tiles();
8370
8371 if(!rect_sel)
8372 {
8373 for(int32_t d=dest1; d <= dest2; ++d)
8374 {
8375 /*unpack_tile(newtilebuf, d, 0, false);
8376
8377 for(int32_t i=0; i<256; i++)
8378 {
8379 if(!backwards)
8380 {
8381 if(!buf[i])
8382 {
8383 buf[i] = unpackbuf[i] + cs;
8384 }
8385 }
8386 else
8387 {
8388 if(unpackbuf[i])
8389 {
8390 buf[i] = unpackbuf[i] + cs;
8391 }
8392 }
8393 }
8394
8395 pack_tile(newtilebuf, buf,d);
8396 */
8397
8398 overlay_tile(newtilebuf,d,src,cs,backwards);
8399
8400 if(!blank_tile_table[src])
8401 {
8402 blank_tile_table[d]=false;
8403 }
8404 }
8405 }
8406 else
8407 {
8408 int32_t rmin=zc_min(TILEROW(dest1),TILEROW(dest2));
8409 int32_t rmax=zc_max(TILEROW(dest1),TILEROW(dest2));
8410 int32_t cmin=zc_min(TILECOL(dest1),TILECOL(dest2));
8411 int32_t cmax=zc_max(TILECOL(dest1),TILECOL(dest2));
8412 int32_t d=0;
8413
8414 for(int32_t j=cmin; j<=cmax; ++j)
8415 {
8416 for(int32_t k=rmin; k<=rmax; ++k)
8417 {
8418 d=j+TILES_PER_ROW*k;
8419 /*unpack_tile(newtilebuf, d, 0, false);
8420
8421 for(int32_t i=0; i<256; i++)
8422 {
8423 if(!backwards)
8424 {
8425 if(!buf[i])
8426 {
8427 buf[i] = unpackbuf[i] + cs;
8428 }
8429 }
8430 else
8431 {
8432 if(unpackbuf[i])
8433 {
8434 buf[i] = unpackbuf[i] + cs;
8435 }
8436 }
8437 }
8438
8439 pack_tile(newtilebuf, buf,d);
8440 */
8441
8442 overlay_tile(newtilebuf,d,src,cs,backwards);
8443
8444 if(!blank_tile_table[src])
8445 {
8446 blank_tile_table[d]=false;
8447 }
8448 }
8449 }
8450 }
8451
8452 return;
8453 }
8454
8455 void sel_tile(int32_t &tile, int32_t &tile2, int32_t &first, int32_t type, int32_t s)
8456 {
8457 tile+=s;
8458 bound(tile,0,NEWMAXTILES-1);
8459
8460 if(type!=0 || !(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
8461 tile2 = tile;
8462
8463 first = tile - (tile%TILES_PER_PAGE);
8464 }
8465
8466 void convert_tile(int32_t t, int32_t bp2, int32_t cs, bool shift, bool alt)
8467 {
8468 int32_t cst;
8469
8470 switch(bp2)
8471 {
8472 case tf4Bit:
8473 switch(newtilebuf[t].format)
8474 {
8475 case tf4Bit:
8476 //already in the right format
8477 break;
8478
8479 case tf8Bit:
8480 unpack_tile(newtilebuf, t, 0, true);
8481
8482 if(alt) //reduce
8483 {
8484 for(int32_t i=0; i<256; i++)
8485 {
8486 if(!shift||unpackbuf[i]!=0)
8487 {
8488 unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
8489 }
8490 }
8491 }
8492 else //truncate
8493 {
8494 for(int32_t i=0; i<256; i++)
8495 {
8496 unpackbuf[i]&=15;
8497 }
8498 }
8499
8500 reset_tile(newtilebuf, t, tf4Bit);
8501 pack_tile(newtilebuf, unpackbuf, t);
8502 break;
8503 }
8504
8505 break;
8506
8507 case tf8Bit:
8508 switch(newtilebuf[t].format)
8509 {
8510 case tf4Bit:
8511 unpack_tile(newtilebuf, t, 0, true);
8512 cst = cs&15;
8513 cst <<= CSET_SHFT;
8514
8515 for(int32_t i=0; i<256; i++)
8516 {
8517 if(!shift||unpackbuf[i]!=0)
8518 {
8519 unpackbuf[i]+=cst;
8520 }
8521 }
8522
8523 reset_tile(newtilebuf, t, tf8Bit);
8524 pack_tile(newtilebuf, unpackbuf, t);
8525 break;
8526
8527 case tf8Bit:
8528 //already in the right format
8529 break;
8530 }
8531
8532 break;
8533 }
8534 }
8535
8536 static DIALOG create_relational_tiles_dlg[] =
8537 {
8538 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
8539 9 { jwin_win_proc, 0, 0, 160, 92, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Tile Setup", NULL, NULL },
8540 9 { jwin_rtext_proc, 74, 28, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Frames:", NULL, NULL },
8541 9 { jwin_edit_proc, 78, 24, 48, 16, 0, 0, 0, 0, 6, 0, NULL, NULL, NULL },
8542 9 { jwin_radio_proc, 8, 44, 64, 9, vc(14), vc(1), 0, D_SELECTED, 0, 0, (void *) "Relational", NULL, NULL },
8543 9 { jwin_radio_proc, 68, 44, 64, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "Dungeon Carving", NULL, NULL },
8544 9 { jwin_button_proc, 10, 66, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
8545 9 { jwin_button_proc, 90, 66, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
8546 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
8547 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
8548 };
8549
8550 void draw_tile_list_window()
8551 {
8552 int32_t w = 640;
8553 int32_t h = 480;
8554
8555 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8556 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
8557 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
8558 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
8559
8560 FONT *oldfont = font;
8561 font = get_zc_font(font_lfont);
8562 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Tile", true);
8563 font=oldfont;
8564 return;
8565 }
8566
8567 void show_blank_tile(int32_t t)
8568 {
8569 char tbuf[80], tbuf2[80], tbuf3[80];
8570 sprintf(tbuf, "Tile is%s blank.", blank_tile_table[t]?"":" not");
8571 sprintf(tbuf2, "%c %c", blank_tile_quarters_table[t*4]?'X':'-', blank_tile_quarters_table[(t*4)+1]?'X':'-');
8572 sprintf(tbuf3, "%c %c", blank_tile_quarters_table[(t*4)+2]?'X':'-', blank_tile_quarters_table[(t*4)+3]?'X':'-');
8573 jwin_alert("Blank Tile Information",tbuf,tbuf2,tbuf3,"&OK",NULL,13,27,get_zc_font(font_lfont));
8574 }
8575
8576 static void do_convert_tile(int32_t tile, int32_t tile2, int32_t cs, bool rect_sel, int format, bool shift, bool alt, bool skip_prompt = false)
8577 {
8578 int num_bits;
8579 if (format == tf4Bit)
8580 num_bits = 4;
8581 else if (format == tf8Bit)
8582 num_bits = 8;
8583 else assert(false);
8584
8585 char buf[80];
8586 sprintf(buf, "Do you want to convert the selected %s to %d-bit color?", tile==tile2?"tile":"tiles",num_bits);
8587
8588 if (skip_prompt || jwin_alert("Convert Tile?",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8589 {
8590 go_tiles();
8591 saved=false;
8592
8593 if(format == tf4Bit)
8594 {
8595 memset(cset_reduce_table, 0, 256);
8596 memset(col_diff,0,3*128);
8597 calc_cset_reduce_table(RAMpal, cs);
8598 }
8599
8600 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8601
8602 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8603 {
8604 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8605 firsttile-=coldiff;
8606 lasttile+=coldiff;
8607 }
8608
8609 for(int32_t t=firsttile; t<=lasttile; t++)
8610 if(!rect_sel ||
8611 ((TILECOL(t)>=TILECOL(firsttile)) &&
8612 (TILECOL(t)<=TILECOL(lasttile))))
8613 convert_tile(t, format, cs, shift, alt);
8614
8615 tile=tile2=zc_min(tile,tile2);
8616 }
8617 }
8618
8619
8620 int32_t readtilefile(PACKFILE *f)
8621 {
8622 dword section_version=0;
8623 dword section_cversion=0;
8624 int32_t zversion = 0;
8625 int32_t zbuild = 0;
8626
8627 if(!p_igetl(&zversion,f))
8628 {
8629 return 0;
8630 }
8631 if(!p_igetl(&zbuild,f))
8632 {
8633 return 0;
8634 }
8635 if(!p_igetw(&section_version,f))
8636 {
8637 return 0;
8638 }
8639 if(!p_igetw(&section_cversion,f))
8640 {
8641 return 0;
8642 }
8643 al_trace("readoneweapon section_version: %d\n", section_version);
8644 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8645
8646 if ( zversion > ZELDA_VERSION )
8647 {
8648 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8649 return 0;
8650 }
8651
8652 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8653 {
8654 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8655 return 0;
8656
8657 }
8658 else
8659 {
8660 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8661 }
8662
8663 int32_t index = 0;
8664 int32_t count = 0;
8665
8666 //tile id
8667 if(!p_igetl(&index,f))
8668 {
8669 return 0;
8670 }
8671 al_trace("Reading tile: index(%d)\n", index);
8672
8673 //tile count
8674 if(!p_igetl(&count,f))
8675 {
8676 return 0;
8677 }
8678 al_trace("Reading tile: count(%d)\n", count);
8679
8680
8681
8682
8683 for ( int32_t tilect = 0; tilect < count; tilect++ )
8684 {
8685 byte *temp_tile = new byte[tilesize(tf32Bit)];
8686 byte format=tf4Bit;
8687 memset(temp_tile, 0, tilesize(tf32Bit));
8688 if(!p_getc(&format,f))
8689 {
8690 delete[] temp_tile;
8691 return 0;
8692 }
8693
8694
8695 if(!pfread(temp_tile,tilesize(format),f))
8696 {
8697 delete[] temp_tile;
8698 return 0;
8699 }
8700
8701 reset_tile(newtilebuf, index+(tilect), format);
8702 memcpy(newtilebuf[index+(tilect)].data,temp_tile,tilesize(newtilebuf[index+(tilect)].format));
8703 delete[] temp_tile;
8704 }
8705
8706
8707 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8708
8709 register_blank_tiles();
8710 register_used_tiles();
8711
8712 return 1;
8713
8714 }
8715
8716 int32_t readtilefile_to_location(PACKFILE *f, int32_t start, int32_t skip)
8717 {
8718 dword section_version=0;
8719 dword section_cversion=0;
8720 int32_t zversion = 0;
8721 int32_t zbuild = 0;
8722
8723 if(!p_igetl(&zversion,f))
8724 {
8725 return 0;
8726 }
8727 if(!p_igetl(&zbuild,f))
8728 {
8729 return 0;
8730 }
8731 if(!p_igetw(&section_version,f))
8732 {
8733 return 0;
8734 }
8735 if(!p_igetw(&section_cversion,f))
8736 {
8737 return 0;
8738 }
8739 al_trace("readoneweapon section_version: %d\n", section_version);
8740 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8741
8742 if ( zversion > ZELDA_VERSION )
8743 {
8744 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8745 return 0;
8746 }
8747
8748 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8749 {
8750 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8751 return 0;
8752
8753 }
8754 else
8755 {
8756 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8757 }
8758
8759 int32_t index = 0;
8760 int32_t count = 0;
8761
8762 //tile id
8763 if(!p_igetl(&index,f))
8764 {
8765 return 0;
8766 }
8767 al_trace("Reading tile: index(%d)\n", index);
8768
8769 //tile count
8770 if(!p_igetl(&count,f))
8771 {
8772 return 0;
8773 }
8774 al_trace("Reading tile: count(%d)\n", count);
8775
8776
8777 for ( int32_t tilect = 0; tilect < count; tilect++ )
8778 {
8779 byte *temp_tile = new byte[tilesize(tf32Bit)];
8780 byte format=tf4Bit;
8781 memset(temp_tile, 0, tilesize(tf32Bit));
8782 if(!p_getc(&format,f))
8783 {
8784 delete[] temp_tile;
8785 return 0;
8786 }
8787
8788
8789 if(!pfread(temp_tile,tilesize(format),f))
8790 {
8791 delete[] temp_tile;
8792 return 0;
8793 }
8794
8795 reset_tile(newtilebuf, start+(tilect), format);
8796 if ( skip )
8797 {
8798 if ( (start+(tilect)) < skip )
8799 {
8800 delete[] temp_tile;
8801 continue;
8802 }
8803
8804 }
8805 if ( start+(tilect) < NEWMAXTILES )
8806 {
8807 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8808 }
8809 delete[] temp_tile;
8810
8811 }
8812
8813
8814 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8815
8816 register_blank_tiles();
8817 register_used_tiles();
8818
8819 return 1;
8820
8821 }
8822
8823
8824 int32_t readtilefile_to_location(PACKFILE *f, int32_t start)
8825 {
8826 dword section_version=0;
8827 dword section_cversion=0;
8828 int32_t zversion = 0;
8829 int32_t zbuild = 0;
8830
8831 if(!p_igetl(&zversion,f))
8832 {
8833 return 0;
8834 }
8835 if(!p_igetl(&zbuild,f))
8836 {
8837 return 0;
8838 }
8839 if(!p_igetw(&section_version,f))
8840 {
8841 return 0;
8842 }
8843 if(!p_igetw(&section_cversion,f))
8844 {
8845 return 0;
8846 }
8847 al_trace("readoneweapon section_version: %d\n", section_version);
8848 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8849
8850 if ( zversion > ZELDA_VERSION )
8851 {
8852 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8853 return 0;
8854 }
8855
8856 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8857 {
8858 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8859 return 0;
8860
8861 }
8862 else
8863 {
8864 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8865 }
8866
8867 int32_t index = 0;
8868 int32_t count = 0;
8869
8870 //tile id
8871 if(!p_igetl(&index,f))
8872 {
8873 return 0;
8874 }
8875 al_trace("Reading tile: index(%d)\n", index);
8876
8877 //tile count
8878 if(!p_igetl(&count,f))
8879 {
8880 return 0;
8881 }
8882 al_trace("Reading tile: count(%d)\n", count);
8883
8884
8885
8886
8887 for ( int32_t tilect = 0; tilect < count; tilect++ )
8888 {
8889 byte *temp_tile = new byte[tilesize(tf32Bit)];
8890 byte format=tf4Bit;
8891 memset(temp_tile, 0, tilesize(tf32Bit));
8892
8893 if(!p_getc(&format,f))
8894 {
8895 delete[] temp_tile;
8896 return 0;
8897 }
8898
8899
8900 if(!pfread(temp_tile,tilesize(format),f))
8901 {
8902 delete[] temp_tile;
8903 return 0;
8904 }
8905
8906 reset_tile(newtilebuf, start+(tilect), format);
8907 if ( start+(tilect) < NEWMAXTILES )
8908 {
8909 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8910 }
8911 delete[] temp_tile;
8912 }
8913
8914
8915 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8916
8917 register_blank_tiles();
8918 register_used_tiles();
8919
8920 return 1;
8921
8922 }
8923 int32_t writetilefile(PACKFILE *f, int32_t index, int32_t count)
8924 {
8925 dword section_version=V_TILES;
8926 dword section_cversion=CV_TILES;
8927 int32_t zversion = ZELDA_VERSION;
8928 int32_t zbuild = VERSION_BUILD;
8929
8930 if(!p_iputl(zversion,f))
8931 {
8932 return 0;
8933 }
8934 if(!p_iputl(zbuild,f))
8935 {
8936 return 0;
8937 }
8938 if(!p_iputw(section_version,f))
8939 {
8940 return 0;
8941 }
8942
8943 if(!p_iputw(section_cversion,f))
8944 {
8945 return 0;
8946 }
8947
8948 //start tile id
8949 if(!p_iputl(index,f))
8950 {
8951 return 0;
8952 }
8953
8954 //count
8955 if(!p_iputl(count,f))
8956 {
8957 return 0;
8958 }
8959
8960 for ( int32_t tilect = 0; tilect < count; tilect++ )
8961 {
8962 if(!p_putc(newtilebuf[index+(tilect)].format,f))
8963 {
8964 return 0;
8965 }
8966 if(!pfwrite(newtilebuf[index+(tilect)].data,tilesize(newtilebuf[index+(tilect)].format),f))
8967 {
8968 return 0;
8969 }
8970 }
8971
8972 return 1;
8973
8974 }
8975
8976 static int32_t _selected_tile=-1, _selected_tcset=-1;
8977 int32_t select_tile(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
8978 {
8979 popup_zqdialog_start();
8980 reset_combo_animations();
8981 reset_combo_animations2();
8982 bound(tile,0,NEWMAXTILES-1);
8983 ex=exnow;
8984 int32_t done=0;
8985 int32_t oflip=flip;
8986 int32_t otile=tile;
8987 int32_t ocs=cs;
8988 int32_t first=(tile/TILES_PER_PAGE)*TILES_PER_PAGE; //first tile on the current page
8989 int32_t copy=-1;
8990 int32_t tile2=tile,copycnt=0;
8991 int32_t tile_clicked=-1;
8992 bool rect_sel=true;
8993 bound(first,0,(TILES_PER_PAGE*TILE_PAGES)-1);
8994 position_mouse_z(0);
8995
8996 go();
8997
8998 register_used_tiles();
8999 int32_t w = 640;
9000 int32_t h = 480;
9001 int32_t window_xofs=(zq_screen_w-w-12)>>1;
9002 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
9003 int32_t screen_xofs=window_xofs+6;
9004 int32_t screen_yofs=window_yofs+25;
9005 int32_t panel_yofs=3;
9006 int32_t mul = 2;
9007 FONT *tfont = get_zc_font(font_lfont_l);
9008
9009 draw_tile_list_window();
9010 int32_t f=0;
9011 draw_tiles(first,cs,f);
9012
9013 if(type==0)
9014 {
9015 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
9016 }
9017 else
9018 {
9019 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
9020 }
9021
9022 go_tiles();
9023
9024 while(gui_mouse_b())
9025 {
9026 /* do nothing */
9027 rest(1);
9028 }
9029
9030 bool bdown=false;
9031
9032 #define FOREACH_START(_t) \
9033 { \
9034 int32_t _first, _last; \
9035 if(is_rect) \
9036 { \
9037 _first=top*TILES_PER_ROW+left; \
9038 _last=_first+rows*TILES_PER_ROW|+columns-1; \
9039 } \
9040 else \
9041 { \
9042 _first=zc_min(tile, tile2); \
9043 _last=zc_max(tile, tile2); \
9044 } \
9045 for(int32_t _t=_first; _t<=_last; _t++) \
9046 { \
9047 if(is_rect) \
9048 { \
9049 int32_t row=TILEROW(_t); \
9050 if(row<top || row>=top+rows) \
9051 continue; \
9052 int32_t col=TILECOL(_t); \
9053 if(col<left || col>=left+columns) \
9054 continue; \
9055 } \
9056
9057 #define FOREACH_END\
9058 } \
9059 }
9060
9061 bool did_snap = false;
9062 int otl = tile, otl2 = tile2;
9063 do
9064 {
9065 HANDLE_CLOSE_ZQDLG();
9066 if(exiting_program) break;
9067 rest(4);
9068 int32_t top=TILEROW(zc_min(tile, tile2));
9069 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
9070 int32_t rows=TILEROW(zc_max(tile, tile2))-top+1;
9071 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
9072 bool is_rect=(rows==1)||(columns==TILES_PER_ROW)||rect_sel;
9073 bool redraw=false;
9074
9075 if(mouse_z!=0)
9076 {
9077 sel_tile(tile,tile2,first,type,((mouse_z/abs(mouse_z))*(-1)*TILES_PER_PAGE));
9078 position_mouse_z(0);
9079 redraw=true;
9080 }
9081
9082 if(keypressed())
9083 {
9084 switch(readkey()>>8)
9085 {
9086 case KEY_ENTER_PAD:
9087 case KEY_ENTER:
9088 done=2;
9089 break;
9090
9091 case KEY_ESC:
9092 done=1;
9093 break;
9094
9095 case KEY_F1:
9096 onHelp();
9097 break;
9098
9099 case KEY_EQUALS:
9100 case KEY_PLUS_PAD:
9101 {
9102 if(CHECK_CTRL_CMD ||
9103 key[KEY_ALT] || key[KEY_ALTGR])
9104 {
9105 FOREACH_START(t)
9106 if(key[KEY_ALT] || key[KEY_ALTGR])
9107 shift_tile_colors(t, 16, false);
9108 else
9109 shift_tile_colors(t, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9110 FOREACH_END
9111
9112 register_blank_tiles();
9113 }
9114 else if(edit_cs)
9115 cs = (cs<13) ? cs+1:0;
9116
9117 redraw=true;
9118 break;
9119 }
9120
9121 case KEY_Z:
9122 case KEY_F12:
9123 {
9124 if(!did_snap)
9125 {
9126 //Export tile page as screenshot
9127 PALETTE temppal;
9128 get_palette(temppal);
9129 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
9130 draw_tiles(tempbmp,first,cs,f,false,true);
9131 save_bitmap(getSnapName(), tempbmp, RAMpal);
9132 destroy_bitmap(tempbmp);
9133
9134 redraw = true;
9135 did_snap = true;
9136 }
9137 break;
9138 }
9139
9140 case KEY_S:
9141 {
9142 if(!prompt_for_new_file_compat("Save ZTILE(.ztile)", "ztile", NULL,datapath,false))
9143 break;
9144 PACKFILE *f=pack_fopen_password(temppath,F_WRITE, "");
9145 if(!f) break;
9146 al_trace("Saving tile: %d\n", tile);
9147 writetilefile(f,tile,1);
9148 pack_fclose(f);
9149 break;
9150 }
9151 case KEY_L:
9152 {
9153 if(!prompt_for_existing_file_compat("Load ZTILE(.ztile)", "ztile", NULL,datapath,false))
9154 break;
9155 PACKFILE *f=pack_fopen_password(temppath,F_READ, "");
9156 if(!f) break;
9157 al_trace("Saving tile: %d\n", tile);
9158 if (!readtilefile(f))
9159 {
9160 al_trace("Could not read from .ztile packfile %s\n", temppath);
9161 jwin_alert("ZTILE File: Error","Could not load the specified Tile.",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9162 }
9163 else
9164 {
9165 jwin_alert("ZTILE File: Success!","Loaded the source tiles to your tile sheets!",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9166 }
9167
9168 pack_fclose(f);
9169 //register_blank_tiles();
9170 //register_used_tiles();
9171 redraw=true;
9172 break;
9173 }
9174 case KEY_MINUS:
9175 case KEY_MINUS_PAD:
9176 {
9177 if(CHECK_CTRL_CMD ||
9178 key[KEY_ALT] || key[KEY_ALTGR])
9179 {
9180 FOREACH_START(t)
9181 if(key[KEY_ALT] || key[KEY_ALTGR])
9182 shift_tile_colors(t, -16, false);
9183 else
9184 shift_tile_colors(t, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9185 FOREACH_END
9186
9187 register_blank_tiles();
9188 }
9189 else if(edit_cs)
9190 cs = (cs>0) ? cs-1:13;
9191
9192 redraw=true;
9193 break;
9194 }
9195
9196 case KEY_UP:
9197 {
9198 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9199 {
9200 case 3: //ALT and CTRL
9201 case 2: //ALT
9202 if(is_rect)
9203 {
9204 saved=false;
9205 go_slide_tiles(columns, rows, top, left);
9206 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9207 bool same = true;
9208
9209 for(int32_t d=0; d<columns; d++)
9210 {
9211 for(int32_t s=0; s<rows; s++)
9212 {
9213 int32_t t=((top+s)*TILES_PER_ROW)+left+d;
9214
9215 if(newtilebuf[t].format!=bitcheck) same = false;
9216 }
9217 }
9218
9219 if(!same) break;
9220
9221 // This used to do something. Too lazy to remove.
9222 // Can probably remove the above "same" check too.
9223 bitcheck = 2;
9224
9225 for(int32_t c=0; c<columns; c++)
9226 {
9227 for(int32_t r=0; r<rows; r++)
9228 {
9229 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9230 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(8*bitcheck));
9231 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data);
9232
9233 for(int32_t pixelrow=0; pixelrow<16*bitcheck; pixelrow++)
9234 {
9235 if(pixelrow==15*bitcheck)
9236 {
9237 int32_t srctile=temptile+TILES_PER_ROW;
9238 if(srctile>=NEWMAXTILES)
9239 srctile-=rows*TILES_PER_ROW;
9240 src_pixelrow=(qword*)(newtilebuf[srctile].data);
9241 }
9242
9243 *dest_pixelrow=*src_pixelrow;
9244 dest_pixelrow++;
9245 src_pixelrow++;
9246 }
9247 }
9248
9249 qword *dest_pixelrow=(qword*)(newtilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9250
9251 for(int32_t b=0; b<bitcheck; b++,dest_pixelrow++)
9252 {
9253 if((CHECK_CTRL_CMD))
9254 {
9255 *dest_pixelrow=0;
9256 }
9257 else
9258 {
9259 qword *src_pixelrow=(qword*)(newundotilebuf[(top*TILES_PER_ROW)+left+c].data+(8*b));
9260 *dest_pixelrow=*src_pixelrow;
9261 }
9262 }
9263 }
9264 }
9265
9266 register_blank_tiles();
9267 redraw=true;
9268 break;
9269
9270 case 1: //CTRL
9271 case 0: //None
9272 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(tile_page_row(tile)*TILES_PER_ROW):-TILES_PER_ROW);
9273 redraw=true;
9274
9275 default: //Others
9276 break;
9277 }
9278 }
9279 break;
9280
9281 case KEY_DOWN:
9282 {
9283 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9284 {
9285 case 3: //ALT and CTRL
9286 case 2: //ALT
9287 if(is_rect)
9288 {
9289 saved=false;
9290 go_slide_tiles(columns, rows, top, left);
9291 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9292 bool same = true;
9293
9294 for(int32_t c=0; c<columns; c++)
9295 {
9296 for(int32_t r=0; r<rows; r++)
9297 {
9298 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9299
9300 if(newtilebuf[t].format!=bitcheck) same = false;
9301 }
9302 }
9303
9304 if(!same) break;
9305
9306 // This used to do something. Too lazy to remove.
9307 // Can probably remove the above "same" check too.
9308 bitcheck = 2;
9309
9310 for(int32_t c=0; c<columns; c++)
9311 {
9312 for(int32_t r=rows-1; r>=0; r--)
9313 {
9314 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9315 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(112*bitcheck)+(8*(bitcheck-1)));
9316 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data+(120*bitcheck)+(8*(bitcheck-1)));
9317
9318 for(int32_t pixelrow=(8<<bitcheck)-1; pixelrow>=0; pixelrow--)
9319 {
9320 if(pixelrow<bitcheck)
9321 {
9322 int32_t srctile=temptile-TILES_PER_ROW;
9323 if(srctile<0)
9324 srctile+=rows*TILES_PER_ROW;
9325 qword *tempsrc=(qword*)(newtilebuf[srctile].data+(120*bitcheck)+(8*pixelrow));
9326 *dest_pixelrow=*tempsrc;
9327 //*dest_pixelrow=0;
9328 }
9329 else
9330 {
9331 *dest_pixelrow=*src_pixelrow;
9332 }
9333
9334 dest_pixelrow--;
9335 src_pixelrow--;
9336 }
9337 }
9338
9339 qword *dest_pixelrow=(qword*)(newtilebuf[(top*TILES_PER_ROW)+left+c].data);
9340 qword *src_pixelrow=(qword*)(newundotilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9341
9342 for(int32_t b=0; b<bitcheck; b++)
9343 {
9344 if((CHECK_CTRL_CMD))
9345 {
9346 *dest_pixelrow=0;
9347 }
9348 else
9349 {
9350 *dest_pixelrow=*src_pixelrow;
9351 }
9352
9353 dest_pixelrow++;
9354 src_pixelrow++;
9355 }
9356 }
9357 }
9358
9359 register_blank_tiles();
9360 redraw=true;
9361 break;
9362
9363 case 1: //CTRL
9364 case 0: //None
9365 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_ROWS_PER_PAGE-1)-tile_page_row(tile))*TILES_PER_ROW:TILES_PER_ROW);
9366 redraw=true;
9367
9368 default: //Others
9369 break;
9370 }
9371 }
9372 break;
9373
9374 case KEY_LEFT:
9375 {
9376 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9377 {
9378 case 3: //ALT and CTRL
9379 case 2: //ALT
9380 if(is_rect)
9381 {
9382 saved=false;
9383 go_slide_tiles(columns, rows, top, left);
9384 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9385 bool same = true;
9386
9387 for(int32_t c=0; c<columns; c++)
9388 {
9389 for(int32_t r=0; r<rows; r++)
9390 {
9391 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9392
9393 if(newtilebuf[t].format!=bitcheck) same = false;
9394 }
9395 }
9396
9397 if(!same) break;
9398
9399 // This used to do something. Too lazy to remove.
9400 // Can probably remove the above "same" check too.
9401 bitcheck = 2;
9402
9403 for(int32_t r=0; r<rows; r++)
9404 {
9405 for(int32_t c=0; c<columns; c++)
9406 {
9407 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9408 byte *dest_pixelrow=(newtilebuf[temptile].data);
9409
9410 for(int32_t pixelrow=0; pixelrow<16; pixelrow++)
9411 {
9412 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9413 {
9414 *dest_pixelrow=*(dest_pixelrow+1);
9415 dest_pixelrow++;
9416 }
9417
9418 if(c==columns-1)
9419 {
9420 if(!(CHECK_CTRL_CMD))
9421 {
9422 byte *tempsrc=(newundotilebuf[((top+r)*TILES_PER_ROW)+left].data+(pixelrow*8*bitcheck));
9423 *dest_pixelrow=*tempsrc;
9424 }
9425 }
9426 else
9427
9428 {
9429 byte *tempsrc=(newtilebuf[temptile+1].data+(pixelrow*8*bitcheck));
9430 *dest_pixelrow=*tempsrc;
9431 }
9432
9433 dest_pixelrow++;
9434 }
9435 }
9436 }
9437
9438 register_blank_tiles();
9439 redraw=true;
9440 }
9441
9442 break;
9443
9444 case 1: //CTRL
9445 case 0: //None
9446 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile%TILES_PER_ROW):-1);
9447 redraw=true;
9448
9449 default: //Others
9450 break;
9451 }
9452 }
9453 break;
9454
9455 case KEY_RIGHT:
9456 {
9457 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9458 {
9459 case 3: //ALT and CTRL
9460 case 2: //ALT
9461 if(is_rect)
9462 {
9463 saved=false;
9464 go_slide_tiles(columns, rows, top, left);
9465 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9466 bool same = true;
9467
9468 for(int32_t c=0; c<columns; c++)
9469 {
9470 for(int32_t r=0; r<rows; r++)
9471 {
9472 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9473
9474 if(newtilebuf[t].format!=bitcheck) same = false;
9475 }
9476 }
9477
9478 if(!same) break;
9479
9480 // This used to do something. Too lazy to remove.
9481 // Can probably remove the above "same" check too.
9482 bitcheck = 2;
9483
9484 for(int32_t r=0; r<rows; r++)
9485 {
9486 for(int32_t c=columns-1; c>=0; c--)
9487 {
9488 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9489 byte *dest_pixelrow=(newtilebuf[temptile].data)+(128*bitcheck)-1;
9490
9491 for(int32_t pixelrow=15; pixelrow>=0; pixelrow--)
9492 {
9493 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9494 {
9495 *dest_pixelrow=*(dest_pixelrow-1);
9496 dest_pixelrow--;
9497 }
9498
9499 if(c==0)
9500 {
9501 if(!(CHECK_CTRL_CMD))
9502 {
9503 byte *tempsrc=(newundotilebuf[(((top+r)*TILES_PER_ROW)+left+columns-1)].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9504 *dest_pixelrow=*tempsrc;
9505 }
9506 }
9507 else
9508 {
9509 byte *tempsrc=(newtilebuf[temptile-1].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9510 *dest_pixelrow=*tempsrc;
9511 }
9512
9513 dest_pixelrow--;
9514 }
9515 }
9516 }
9517
9518 register_blank_tiles();
9519 redraw=true;
9520 }
9521
9522 break;
9523
9524 case 1: //CTRL
9525 case 0: //None
9526 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILES_PER_ROW)-(tile%TILES_PER_ROW)-1:1);
9527 redraw=true;
9528
9529 default: //Others
9530 break;
9531 }
9532 }
9533 break;
9534
9535 case KEY_PGUP:
9536 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(TILEROW(tile)*TILES_PER_ROW):-TILES_PER_PAGE);
9537 redraw=true;
9538 break;
9539
9540 case KEY_PGDN:
9541 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_PAGES*TILE_ROWS_PER_PAGE)-TILEROW(tile)-1)*TILES_PER_ROW:TILES_PER_PAGE);
9542 redraw=true;
9543 break;
9544
9545 case KEY_HOME:
9546 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile):-(tile%TILES_PER_PAGE));
9547 redraw=true;
9548 break;
9549
9550 case KEY_END:
9551 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILE_PAGES)*(TILES_PER_PAGE)-tile-1:(TILES_PER_PAGE)-(tile%TILES_PER_PAGE)-1);
9552 redraw=true;
9553 break;
9554
9555 case KEY_P:
9556 {
9557 int32_t whatPage = gettilepagenumber("Goto Page", (PreFillTileEditorPage?(first/TILES_PER_PAGE):0));
9558
9559 if(whatPage >= 0)
9560 sel_tile(tile,tile2,first,type,((whatPage-TILEPAGE(tile))*TILE_ROWS_PER_PAGE)*TILES_PER_ROW);
9561
9562 break;
9563 }
9564
9565 case KEY_O:
9566 if(type==0 && copy>=0)
9567 {
9568 go_tiles();
9569
9570 if(key[KEY_LSHIFT] ||key[KEY_RSHIFT])
9571 {
9572 mass_overlay_tile(zc_min(tile,tile2),zc_max(tile,tile2),copy,cs,(CHECK_CTRL_CMD), rect_sel);
9573 saved=false;
9574 }
9575 else
9576 {
9577 saved = !overlay_tiles(tile,tile2,copy,copycnt,rect_sel,false,cs,(CHECK_CTRL_CMD));
9578 //overlay_tile(newtilebuf,tile,copy,cs,(CHECK_CTRL_CMD));
9579 }
9580
9581 saved=false;
9582 redraw=true;
9583 }
9584
9585 break;
9586
9587 case KEY_E:
9588 if(type==0)
9589 {
9590 edit_tile(tile,flip,cs);
9591 draw_tile_list_window();
9592 redraw=true;
9593 }
9594
9595 break;
9596
9597 case KEY_G:
9598 if(type==0)
9599 {
9600 grab_tile(tile,cs);
9601 draw_tile_list_window();
9602 redraw=true;
9603 }
9604
9605 break;
9606
9607 case KEY_C:
9608 copy=zc_min(tile,tile2);
9609 copycnt=abs(tile-tile2)+1;
9610 redraw=true;
9611 break;
9612
9613 case KEY_X:
9614 if(type==2)
9615 {
9616 ex=(ex+1)%3;
9617 }
9618
9619 break;
9620
9621 case KEY_R:
9622 if(type==2)
9623 break;
9624 if(type==1)
9625 {
9626 flip = rotate_value(flip);
9627 redraw=true;
9628 break;
9629 }
9630
9631 go_tiles();
9632
9633 if(CHECK_CTRL_CMD)
9634 {
9635 bool go=false;
9636 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
9637 go=true;
9638 else if(massRecolorSetup(cs))
9639 go=true;
9640
9641 if(go)
9642 {
9643 FOREACH_START(t)
9644 massRecolorApply(t);
9645 FOREACH_END
9646
9647 register_blank_tiles();
9648 }
9649 }
9650 else
9651 {
9652 FOREACH_START(t)
9653 rotate_tile(t,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
9654 FOREACH_END
9655 }
9656
9657 redraw=true;
9658 saved=false;
9659 break;
9660
9661 case KEY_SPACE:
9662 rect_sel=!rect_sel;
9663 copy=-1;
9664 redraw=true;
9665 break;
9666
9667 case KEY_H:
9668 flip^=1;
9669 go_tiles();
9670
9671 if(type==0)
9672 {
9673 normalize(tile,tile2,rect_sel,flip);
9674 flip=0;
9675 }
9676
9677 redraw=true;
9678 break;
9679
9680
9681 case KEY_V:
9682 if(copy==-1)
9683 {
9684 if(type!=2)
9685 {
9686 flip^=2;
9687 go_tiles();
9688
9689 if(type==0)
9690 {
9691 normalize(tile,tile2,rect_sel,flip);
9692 flip=0;
9693 }
9694 }
9695 }
9696 else
9697 {
9698 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9699 go_tiles();
9700 saved = !copy_tiles(tile,tile2,copy,copycnt,rect_sel,false);
9701 }
9702
9703 redraw=true;
9704 break;
9705
9706 case KEY_F:
9707 if(copy==-1)
9708 {
9709 break;
9710 }
9711 else
9712 {
9713 go_tiles();
9714 {
9715 saved = !copy_tiles_floodfill(tile,tile2,copy,copycnt,rect_sel,false);
9716 }
9717 }
9718
9719 redraw=true;
9720 break;
9721
9722 case KEY_DEL:
9723 if(type==0 && (key[KEY_LSHIFT]||key[KEY_RSHIFT]))
9724 {
9725 bool warn = (rect_sel
9726 && ((tile/20)!=(tile2/20))
9727 && !(tile%20==0&&tile2%20==19));
9728 int32_t z=zc_min(tile,tile2);
9729 int32_t count = abs(tile-tile2) + 1;
9730 tile=z;
9731 tile2=NEWMAXTILES;
9732 copy = tile + count;
9733 copycnt = NEWMAXTILES-copy;
9734 char buf[64];
9735
9736 if(count>1)
9737 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9738 else
9739 sprintf(buf,"Remove tile %d?",tile);
9740
9741 AlertDialog("Remove Tiles", std::string(buf)
9742 +"\nThis will offset the tiles that follow!"
9743 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9744 [&](bool ret,bool)
9745 {
9746 if(ret)
9747 {
9748 go_tiles();
9749 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9750 {
9751 redraw=true;
9752 saved=false;
9753 }
9754 }
9755 }).show();
9756 }
9757 delete_tiles(tile,tile2,rect_sel);
9758 redraw=true;
9759 break;
9760
9761 case KEY_U:
9762 {
9763 if(CHECK_CTRL_CMD)
9764 {
9765 //Only toggle the first 2 bits!
9766 show_only_unused_tiles = (show_only_unused_tiles&~3) | (((show_only_unused_tiles&3)+1)%4);
9767 }
9768 else
9769 {
9770 comeback_tiles();
9771 }
9772
9773 redraw=true;
9774 }
9775 break;
9776
9777 case KEY_8:
9778 case KEY_8_PAD:
9779 hide_8bit_marker();
9780 break;
9781
9782 case KEY_I: //insert tiles
9783 if(type==0)
9784 {
9785 bool warn = (rect_sel
9786 && ((tile/20)!=(tile2/20))
9787 && !(tile%20==0&&tile2%20==19));
9788 int32_t z=zc_min(tile,tile2);
9789 int32_t count = abs(tile-tile2) + 1;
9790 tile=z;
9791 tile2=NEWMAXTILES;
9792 copy = tile + count;
9793 copycnt = NEWMAXTILES-copy;
9794
9795 if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) //Remove
9796 {
9797 char buf[64];
9798
9799 if(count>1)
9800 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9801 else
9802 sprintf(buf,"Remove tile %d?",tile);
9803
9804 AlertDialog("Remove Tiles", std::string(buf)
9805 +"\nThis will offset the tiles that follow!"
9806 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9807 [&](bool ret,bool)
9808 {
9809 if(ret)
9810 {
9811 go_tiles();
9812 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9813 {
9814 redraw=true;
9815 saved=false;
9816 }
9817 }
9818 }).show();
9819 }
9820 else
9821 {
9822 char buf[64];
9823
9824 if(count>1)
9825 sprintf(buf,"Insert %d blank tiles?",count);
9826 else
9827 sprintf(buf,"Insert a blank tile?");
9828
9829 AlertDialog("Insert Tiles", std::string(buf)
9830 +"\nThis will offset the tiles that follow!"
9831 +(warn?"\nInserting tiles ignores rectangular selections!":""),
9832 [&](bool ret,bool)
9833 {
9834 if(ret)
9835 {
9836 go_tiles();
9837 if(copy_tiles(copy,tile2,tile,copycnt,false,true))
9838 {
9839 redraw=true;
9840 saved=false;
9841 }
9842 }
9843 }).show();
9844 }
9845
9846 copy=-1;
9847 tile2=tile=z;
9848 }
9849 break;
9850 case KEY_M:
9851 if(type==0)
9852 {
9853 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
9854 {
9855 go_tiles();
9856 if(copy_tiles(tile,tile2,copy,copycnt,rect_sel,true))
9857 saved=false;
9858 }
9859 else if(copy==-1)
9860 {
9861 // I don't know what this was supposed to be doing before.
9862 // It didn't work in anything like a sensible way.
9863 if(rect_sel)
9864 {
9865 make_combos_rect(top, left, rows, columns, cs);
9866 }
9867 else
9868 {
9869 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
9870 }
9871 }
9872
9873 redraw=true;
9874 }
9875 break;
9876
9877 case KEY_D:
9878 {
9879 int32_t frames=1;
9880 char buf[80];
9881 sprintf(buf, "%d", frames);
9882 create_relational_tiles_dlg[0].dp2=get_zc_font(font_lfont);
9883 create_relational_tiles_dlg[2].dp=buf;
9884
9885 large_dialog(create_relational_tiles_dlg);
9886
9887 int32_t ret=do_zqdialog(create_relational_tiles_dlg,2);
9888
9889 if(ret==5)
9890 {
9891 frames=zc_max(atoi(buf),1);
9892 bool same = true;
9893 int32_t bitcheck=newtilebuf[tile].format;
9894
9895 for(int32_t t=1; t<frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); ++t)
9896 {
9897 if(newtilebuf[tile+t].format!=bitcheck) same = false;
9898 }
9899
9900 if(!same)
9901 {
9902 jwin_alert("Error","The source tiles are not","in the same format.",NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9903 break;
9904 }
9905
9906 if(tile+(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96))>NEWMAXTILES)
9907 {
9908 jwin_alert("Error","Too many tiles will be created",NULL,NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9909 break;
9910 }
9911
9912 for(int32_t i=frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); i<(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96)); ++i)
9913 {
9914 reset_tile(newtilebuf, tile+i, bitcheck);
9915 }
9916
9917 if(create_relational_tiles_dlg[3].flags&D_SELECTED)
9918 {
9919 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9920 {
9921 for(int32_t j=0; j<frames; ++j)
9922 {
9923 merge_tiles(tile+(i*frames)+j, (tile+(relational_template[i][0]*frames)+j)<<2, ((tile+(relational_template[i][1]*frames)+j)<<2)+1, ((tile+(relational_template[i][2]*frames)+j)<<2)+2, ((tile+(relational_template[i][3]*frames)+j)<<2)+3);
9924 }
9925 }
9926 }
9927 else
9928 {
9929 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9930 {
9931 for(int32_t j=0; j<frames; ++j)
9932 {
9933 merge_tiles(tile+(i*frames)+j, (tile+(dungeon_carving_template[i][0]*frames)+j)<<2, ((tile+(dungeon_carving_template[i][1]*frames)+j)<<2)+1, ((tile+(dungeon_carving_template[i][2]*frames)+j)<<2)+2, ((tile+(dungeon_carving_template[i][3]*frames)+j)<<2)+3);
9934 }
9935 }
9936 }
9937 }
9938 register_blank_tiles();
9939 register_used_tiles();
9940 redraw=true;
9941 saved=false;
9942 break;
9943 }
9944
9945 case KEY_B:
9946 {
9947 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9948 bool control=(CHECK_CTRL_CMD);
9949 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9950 int format = control ? tf4Bit : tf8Bit;
9951
9952 do_convert_tile(tile, tile2, cs, rect_sel, format, shift, alt);
9953 register_blank_tiles();
9954 }
9955 break;
9956 }
9957
9958 clear_keybuf();
9959 }
9960
9961 if(!(key[KEY_Z] || key[KEY_F12]))
9962 did_snap = false;
9963
9964 if(gui_mouse_b()&1)
9965 {
9966 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
9967 {
9968 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
9969 {
9970 done=1;
9971 }
9972 }
9973
9974 int32_t x=gui_mouse_x()-screen_xofs;
9975 int32_t y=gui_mouse_y()-screen_yofs;
9976
9977 if(y>=0 && y<208*mul)
9978 {
9979 x=zc_min(zc_max(x,0),(320*mul)-1);
9980 int32_t t = (y>>(5))*TILES_PER_ROW + (x>>(5)) + first;
9981
9982 if(type==0 && (key[KEY_LSHIFT] || key[KEY_RSHIFT]))
9983 {
9984 tile2=t;
9985 }
9986 else
9987 {
9988 tile=tile2=t;
9989 }
9990
9991 if(tile_clicked!=t)
9992 {
9993 dclick_status=DCLICK_NOT;
9994 }
9995 else if(dclick_status == DCLICK_AGAIN)
9996 {
9997 while(gui_mouse_b())
9998 {
9999 /* do nothing */
10000 rest(1);
10001 }
10002
10003 if(((y>>(5))*TILES_PER_ROW + (x>>(5)) + first)!=t)
10004 {
10005 dclick_status=DCLICK_NOT;
10006 }
10007 else
10008 {
10009 if(type==0)
10010 {
10011 edit_tile(tile,flip,cs);
10012 draw_tile_list_window();
10013 redraw=true;
10014 }
10015 else
10016 {
10017 done=2;
10018 }
10019 }
10020 }
10021
10022 tile_clicked=t;
10023 }
10024 else if(x>300*mul && !bdown)
10025 {
10026 if(y<224*mul && first>0)
10027 {
10028 first-=TILES_PER_PAGE;
10029 redraw=true;
10030 }
10031
10032 if(y>=224*mul && first<TILES_PER_PAGE*(TILE_PAGES-1))
10033 {
10034 first+=TILES_PER_PAGE;
10035 redraw=true;
10036 }
10037
10038 bdown=true;
10039 }
10040
10041 if(type==1||type==2)
10042 {
10043 if(!bdown && isinRect(x,y,8*mul,216*mul+panel_yofs,23*mul,231*mul+panel_yofs))
10044 done=1;
10045
10046 if(!bdown && isinRect(x,y,148*mul,216*mul+panel_yofs,163*mul,231*mul+panel_yofs))
10047 done=2;
10048 }
10049 else if(!bdown && isinRect(x,y,127*mul,216*mul+panel_yofs,(127+15)*mul,(216+15)*mul+panel_yofs))
10050 {
10051 rect_sel=!rect_sel;
10052 copy=-1;
10053 redraw=true;
10054 }
10055 else if(!bdown && isinRect(x,y,150*mul,213*mul+panel_yofs,(150+28)*mul,(213+21)*mul+panel_yofs))
10056 {
10057 FONT *tf = font;
10058 font = tfont;
10059
10060 if(do_text_button(150*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Grab"))
10061 {
10062 font = tf;
10063 grab_tile(tile,cs);
10064 draw_tile_list_window();
10065 position_mouse_z(0);
10066 redraw=true;
10067 }
10068
10069 font = tf;
10070 }
10071 else if(!bdown && isinRect(x,y,(150+28)*mul,213*mul+panel_yofs,(150+28*2)*mul,(213+21)*mul+panel_yofs+21))
10072 {
10073 FONT *tf = font;
10074 font = tfont;
10075
10076 if(do_text_button((150+28)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Edit"))
10077 {
10078 font = tf;
10079 edit_tile(tile,flip,cs);
10080 draw_tile_list_window();
10081 redraw=true;
10082 }
10083
10084 font = tf;
10085 }
10086 else if(!bdown && isinRect(x,y,(150+28*2)*mul,213*mul+panel_yofs,(150+28*3)*mul,(213+21)*mul+panel_yofs))
10087 {
10088 FONT *tf = font;
10089 font = tfont;
10090
10091 if(do_text_button((150+28*2)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Export"))
10092 {
10093 std::string initial_path = "tileset.png";
10094 if (strlen(datapath))
10095 initial_path = fmt::format("{}/{}", datapath, initial_path);
10096 if(prompt_for_new_file_compat("Export Tile Page (.png)","png",NULL,initial_path,true))
10097 {
10098 PALETTE temppal;
10099 get_palette(temppal);
10100 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
10101 draw_tiles(tempbmp,first,cs,f,false,true);
10102 save_bitmap(temppath, tempbmp, RAMpal);
10103 destroy_bitmap(tempbmp);
10104 }
10105 }
10106
10107 font = tf;
10108 }
10109 else if(!bdown && isinRect(x,y,(150+28*3)*mul,213*mul+panel_yofs,(150+28*4)*mul,(213+21)*mul+panel_yofs))
10110 {
10111 FONT *tf = font;
10112 font = tfont;
10113
10114 if(do_text_button((150+28*3)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Recolor"))
10115 {
10116 if(massRecolorSetup(cs))
10117 {
10118 go_tiles();
10119
10120 FOREACH_START(t)
10121 massRecolorApply(t);
10122 FOREACH_END
10123
10124 register_blank_tiles();
10125 }
10126 }
10127
10128 font = tf;
10129 }
10130 else if(!bdown && isinRect(x,y,(150+28*4)*mul,213*mul+panel_yofs,(150+28*5)*mul,(213+21)*mul+panel_yofs))
10131 {
10132 FONT *tf = font;
10133 font = tfont;
10134
10135 if(do_text_button((150+28*4)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Done"))
10136 {
10137 done=1;
10138 }
10139
10140 font = tf;
10141 }
10142
10143 bdown=true;
10144 }
10145
10146 bool r_click = false;
10147
10148 if(gui_mouse_b()&2 && !bdown && type==0)
10149 {
10150 int32_t x=(gui_mouse_x()-screen_xofs);//&0xFF0;
10151 int32_t y=(gui_mouse_y()-screen_yofs);//&0xF0;
10152
10153 if(y>=0 && y<208*mul)
10154 {
10155 x=zc_min(zc_max(x,0),(320*mul)-1);
10156 int32_t t = ((y)>>(5))*TILES_PER_ROW + ((x)>>(5)) + first;
10157
10158 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
10159 tile=tile2=t;
10160 }
10161
10162 bdown = r_click = true;
10163 f=8;
10164 }
10165
10166 if(gui_mouse_b()==0)
10167 bdown=false;
10168
10169 position_mouse_z(0);
10170
10171 REDRAW:
10172
10173 if((f%8)==0 || InvalidBG == 1)
10174 redraw=true;
10175 if(otl != tile || otl2 != tile2)
10176 {
10177 otl = tile;
10178 otl2 = tile2;
10179 redraw = true;
10180 }
10181
10182 if(redraw)
10183 {
10184 draw_tiles(first,cs,f);
10185 }
10186 if(f&8)
10187 {
10188 if(rect_sel)
10189 {
10190 for(int32_t i=zc_min(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10191 zc_min(TILECOL(tile),TILECOL(tile2));
10192 i<=zc_max(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10193 zc_max(TILECOL(tile),TILECOL(tile2)); i++)
10194 {
10195 if(i>=first && i<first+TILES_PER_PAGE &&
10196 TILECOL(i)>=zc_min(TILECOL(tile),TILECOL(tile2)) &&
10197 TILECOL(i)<=zc_max(TILECOL(tile),TILECOL(tile2)))
10198 {
10199 int32_t x=TILECOL(i)<<(5);
10200 int32_t y=TILEROW(i-first)<<(5);
10201 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10202 }
10203 }
10204 }
10205 else
10206 {
10207 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
10208 {
10209 if(i>=first && i<first+TILES_PER_PAGE)
10210 {
10211 int32_t x=TILECOL(i)<<(5);
10212 int32_t y=TILEROW(i-first)<<(5);
10213 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10214 }
10215 }
10216 }
10217 }
10218
10219 if(type==0)
10220 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
10221 else
10222 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
10223
10224 if(type==2)
10225 {
10226 char cbuf[16];
10227 sprintf(cbuf, "E&xtend: %s",ex==2 ? "32x32" : ex==1 ? "32x16" : "16x16");
10228 gui_textout_ln(screen, get_zc_font(font_lfont_l), (uint8_t *)cbuf, (235*mul)+screen_xofs, (212*mul)+screen_yofs+panel_yofs, jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
10229 }
10230
10231 ++f;
10232
10233 if(r_click)
10234 {
10235 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_USED, HIDE_USED);
10236 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_UNUSED, HIDE_UNUSED);
10237 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_BLANK, HIDE_BLANK);
10238 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_8BIT, HIDE_8BIT_MARKER);
10239
10240 int current_tile_format = MENUID_SELTILE_COLOR_DEPTH_4_BIT;
10241 if (newtilebuf[tile].format == tf8Bit)
10242 current_tile_format = MENUID_SELTILE_COLOR_DEPTH_8_BIT;
10243 select_tile_color_depth_menu.select_only_uid(current_tile_format);
10244 select_tile_color_depth_cb = [&](int format){
10245 if (newtilebuf[tile].format == format)
10246 return;
10247
10248 bool skip_prompt = true;
10249 do_convert_tile(tile, tile2, cs, rect_sel, format, false, false, skip_prompt);
10250 };
10251
10252 NewMenu rcmenu
10253 {
10254 { "Copy", [&]()
10255 {
10256 copy = zc_min(tile,tile2);
10257 copycnt = abs(tile-tile2)+1;
10258 } },
10259 { "Paste", [&]()
10260 {
10261 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, false);
10262 if(saved) saved = !b;
10263 }, nullopt, copy < 0 },
10264 { "Move", [&]()
10265 {
10266 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, true);
10267 if(saved) saved = !b;
10268 }, nullopt, copy < 0 },
10269 { "Clear", [&]()
10270 {
10271 delete_tiles(tile, tile2, rect_sel);
10272 } },
10273 {},
10274 { "Edit", [&]()
10275 {
10276 edit_tile(tile, flip, cs);
10277 draw_tile_list_window();
10278 } },
10279 { "Grab", [&]()
10280 {
10281 grab_tile(tile, cs);
10282 draw_tile_list_window();
10283 position_mouse_z(0);
10284 } },
10285 { "Scale", [&]()
10286 {
10287 bool b = scale_or_rotate_tiles(tile, tile2, cs, false);
10288 if(saved) saved = !b;
10289 }, nullopt, type != 0 },
10290 { "Angular Rotation", [&]()
10291 {
10292 bool b = scale_or_rotate_tiles(tile, tile2, cs, true);
10293 if(saved) saved = !b;
10294 }, nullopt, type != 0 },
10295 { "Color Depth", &select_tile_color_depth_menu },
10296 {},
10297 { "Blank?", [&]()
10298 {
10299 show_blank_tile(tile);
10300 } },
10301 {},
10302 { "View ", &select_tile_view_menu },
10303 { "Overlay", [&]()
10304 {
10305 overlay_tile(newtilebuf, tile, copy, cs, 0);
10306 } },
10307 { "H-Flip", [&]()
10308 {
10309 flip ^= 1;
10310 go_tiles();
10311
10312 if(type == 0)
10313 {
10314 normalize(tile, tile2, rect_sel, flip);
10315 flip = 0;
10316 }
10317 } },
10318 { "V-Flip", [&]()
10319 {
10320 flip ^= 2;
10321 go_tiles();
10322
10323 if(type == 0)
10324 {
10325 normalize(tile, tile2, rect_sel, flip);
10326 flip = 0;
10327 }
10328 } },
10329 { "Create Combos", [&]()
10330 {
10331 if(rect_sel)
10332 make_combos_rect(top, left, rows, columns, cs);
10333 else
10334 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
10335 }, nullopt, type != 0 },
10336 { "Insert", [&]()
10337 {
10338 bool warn = (rect_sel
10339 && ((tile/20)!=(tile2/20))
10340 && !(tile%20==0&&tile2%20==19));
10341 int32_t z = zc_min(tile, tile2);
10342 int32_t count = abs(tile-tile2) + 1;
10343 tile = z;
10344 tile2 = NEWMAXTILES;
10345 copy = tile + count;
10346 copycnt = NEWMAXTILES-copy;
10347
10348 string msg;
10349
10350 if(count>1)
10351 msg = fmt::format("Insert {} blank tiles?",count);
10352 else
10353 msg = "Insert a blank tile?";
10354
10355 AlertDialog("Insert Tiles", msg
10356 +"\nThis will offset the tiles that follow!"
10357 +(warn?"\nInserting tiles ignores rectangular selections!":""),
10358 [&](bool ret,bool)
10359 {
10360 if(ret)
10361 {
10362 go_tiles();
10363 if(copy_tiles(copy, tile2, tile, copycnt, false, true))
10364 saved = false;
10365 }
10366 }).show();
10367
10368 copy=-1;
10369 tile2=tile=z;
10370 }, nullopt, type != 0 },
10371 { "Remove", [&]()
10372 {
10373 bool warn = (rect_sel
10374 && ((tile/20)!=(tile2/20))
10375 && !(tile%20==0&&tile2%20==19));
10376 int32_t z = zc_min(tile, tile2);
10377 int32_t count = abs(tile-tile2) + 1;
10378 tile = z;
10379 tile2 = NEWMAXTILES;
10380 copy = tile + count;
10381 copycnt = NEWMAXTILES-copy;
10382
10383 string msg;
10384
10385 if(count>1)
10386 msg = fmt::format("Remove tiles {} - {}?", tile, copy-1);
10387 else
10388 msg = fmt::format("Remove tile {}?", tile);
10389
10390 AlertDialog("Remove Tiles", msg
10391 +"\nThis will offset the tiles that follow!"
10392 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
10393 [&](bool ret,bool)
10394 {
10395 if(ret)
10396 {
10397 go_tiles();
10398 if(copy_tiles(tile, tile2, copy, copycnt, false, true))
10399 saved = false;
10400 }
10401 }).show();
10402
10403 copy=-1;
10404 tile2=tile=z;
10405 }, nullopt, type != 0 },
10406 };
10407 rcmenu.pop(window_mouse_x(),window_mouse_y());
10408 redraw = true;
10409 r_click = false;
10410 goto REDRAW;
10411 }
10412 update_hw_screen();
10413 }
10414 while(!done);
10415
10416 while(gui_mouse_b())
10417 {
10418 /* do nothing */
10419 rest(1);
10420 }
10421
10422 comeback();
10423 register_blank_tiles();
10424 register_used_tiles();
10425 setup_combo_animations();
10426 setup_combo_animations2();
10427 int32_t ret = done-1;
10428 if(ret)
10429 {
10430 _selected_tile = tile;
10431 _selected_tcset = cs;
10432 }
10433
10434 popup_zqdialog_end();
10435 return ret;
10436 }
10437 int32_t select_tile_2(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
10438 {
10439 if(_selected_tile > -1)
10440 {
10441 tile = _selected_tile;
10442 cs = _selected_tcset;
10443 }
10444 int32_t ret = select_tile(tile,flip,type,cs,edit_cs,exnow,always_use_flip);
10445 if(_selected_tile < 0)
10446 {
10447 _selected_tile = tile;
10448 _selected_tcset = cs;
10449 }
10450 return ret;
10451 }
10452
10453 int32_t onTiles()
10454 {
10455 return onGotoTiles(-1);
10456 }
10457
10458 int32_t onGotoTiles(int32_t startfrom)
10459 {
10460 static int32_t t = 0;
10461 if (startfrom > -1)
10462 t = startfrom;
10463 int32_t f = 0;
10464 int32_t c = CSet;
10465 reset_pal_cycling();
10466 // loadlvlpal(Map.CurrScr()->color);
10467 rebuild_trans_table();
10468 select_tile(t, f, 0, c, true);
10469 refresh(rALL);
10470 return D_O_K;
10471 }
10472
10473 int32_t combopage_animate = 1;
10474 void draw_combo(BITMAP *dest, int x,int y,int c,int cs,bool animate)
10475 {
10476 if(unsigned(c)<MAXCOMBOS)
10477 {
10478 newcombo& cmb = combobuf[c];
10479 int t = cmb.tile;
10480 if(!animate)
10481 cmb.tile = cmb.o_tile;
10482 put_combo(dest,x,y,c,cs,0,0);
10483 cmb.tile = t;
10484 }
10485 else
10486 {
10487 rectfill(dest,x,y,x+32-1,y+32-1,0);
10488 }
10489 }
10490
10491 void draw_combos(int32_t page,int32_t cs,bool cols)
10492 {
10493 clear_bitmap(screen2);
10494 BITMAP *buf = create_bitmap_ex(8,16,16);
10495
10496 int32_t w = 32;
10497 int32_t h = 32;
10498 int32_t mul = 2;
10499
10500 int32_t window_xofs=(zq_screen_w-640-12)>>1;
10501 int32_t window_yofs=(zq_screen_h-480-25-6)>>1;
10502 int32_t screen_xofs=window_xofs+6;
10503 int32_t screen_yofs=window_yofs+25;
10504
10505 if(cols==false)
10506 {
10507 for(int32_t i=0; i<256; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
10508 {
10509 int32_t x = (i%COMBOS_PER_ROW)*w;
10510 int32_t y = (i/COMBOS_PER_ROW)*h;
10511
10512 combotile_override_x = x+screen_xofs+(w-16)/2;
10513 combotile_override_y = y+screen_yofs+(h-16)/2;
10514 draw_combo(buf,0,0,i+(page<<8),cs,combopage_animate);
10515 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10516 }
10517 }
10518 else
10519 {
10520 int32_t c = 0;
10521
10522 for(int32_t i=0; i<256; i++)
10523 {
10524 int32_t x = (i%COMBOS_PER_ROW)*w;
10525 int32_t y = (i/COMBOS_PER_ROW)*h;
10526
10527 combotile_override_x = x+screen_xofs+(w-16)/2;
10528 combotile_override_y = y+screen_yofs+(h-16)/2;
10529 draw_combo(buf,0,0,c+(page<<8),cs,combopage_animate);
10530 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10531 ++c;
10532
10533 if((i&3)==3)
10534 c+=48;
10535
10536 if((i%COMBOS_PER_ROW)==(COMBOS_PER_ROW-1))
10537 c-=256;
10538 }
10539 }
10540 combotile_override_x = combotile_override_y = -1;
10541
10542 for(int32_t x=(64*mul); x<(320*mul); x+=(64*mul))
10543 {
10544 vline(screen2,x,0,(208*mul)-1,vc(15));
10545 }
10546
10547 destroy_bitmap(buf);
10548 }
10549
10550 void combo_info(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,int32_t buttons)
10551 {
10552 int32_t yofs=3;
10553 static BITMAP *buf = create_bitmap_ex(8,16,16);
10554 int32_t mul = 2;
10555 FONT *tfont = get_zc_font(font_lfont_l);
10556
10557 rectfill(screen2,0,210*2,(320*2)-1,(240*2)-1,jwin_pal[jcBOX]);
10558 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
10559 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
10560
10561 jwin_draw_frame(screen2,(31*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10562
10563 if(copy>=0)
10564 {
10565 put_combo(buf,0,0,copy,cs,0,0);
10566 stretch_blit(buf,screen2,0,0,16,16,31*mul,216*mul+yofs,16*mul,16*mul);
10567
10568 if(copycnt>1)
10569 {
10570 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
10571 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
10572 }
10573 else
10574 {
10575 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
10576 }
10577 }
10578 else
10579 {
10580 if (InvalidBG == 2)
10581 {
10582 draw_checkerboard(screen2, 31 * mul, 216 * mul + yofs, 16 * mul);
10583 }
10584 else if(InvalidBG == 1)
10585 {
10586 for(int32_t dy=0; dy<16*mul; dy++)
10587 {
10588 for(int32_t dx=0; dx<16*mul; dx++)
10589 {
10590 screen2->line[(216*mul)+yofs+dy][(31*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10591 }
10592 }
10593 }
10594 else
10595 {
10596 rectfill(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(0));
10597 rect(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10598 line(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10599 line(screen2, (31*mul), (216*mul)+yofs+31, (31*mul)+31, (216*mul)+yofs, vc(15));
10600 }
10601 }
10602
10603 jwin_draw_frame(screen2,(53*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10604 put_combo(buf,0,0,tile,cs,0,0);
10605 stretch_blit(buf,screen2,0,0,16,16,53*mul,216*mul+yofs,16*mul,16*mul);
10606
10607 if(tile>tile2)
10608 {
10609 zc_swap(tile,tile2);
10610 }
10611
10612 char cbuf[8];
10613 cbuf[0]=0;
10614
10615 if(tile2!=tile)
10616 {
10617 sprintf(cbuf,"-%d",tile2);
10618 }
10619
10620 textprintf_ex(screen2,tfont,(73*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"combo: CSet %d", cs);
10621 textprintf_ex(screen2,tfont,(73*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,cbuf);
10622
10623 if(tile2==tile)
10624 {
10625 int32_t nextcombo=combobuf[tile].nextcombo;
10626 int32_t nextcset=(combobuf[tile].animflags & AF_CYCLENOCSET) ? cs : combobuf[tile].nextcset;
10627 jwin_draw_frame(screen2,(136*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10628
10629 if(nextcombo>0)
10630 {
10631 put_combo(buf,0,0,nextcombo,nextcset,0,0);
10632 stretch_blit(buf,screen2,0,0,16,16,136*mul,216*mul+yofs,16*mul,16*mul);
10633 }
10634 else
10635 {
10636 if (InvalidBG == 2)
10637 {
10638 draw_checkerboard(screen2, 136 * mul, 216 * mul + yofs, 16 * mul);
10639 }
10640 else if(InvalidBG == 1)
10641 {
10642 for(int32_t dy=0; dy<16*mul; dy++)
10643 {
10644 for(int32_t dx=0; dx<16*mul; dx++)
10645 {
10646 screen2->line[(216*mul)+yofs+dy][(136*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10647 }
10648 }
10649 }
10650 else
10651 {
10652 rectfill(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(0));
10653 rect(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10654 line(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10655 line(screen2, (136*mul), (216*mul)+yofs+31, (136*mul)+31, (216*mul)+yofs, vc(15));
10656 }
10657 }
10658
10659 textprintf_right_ex(screen2,tfont,(132*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Cycle:");
10660 textprintf_right_ex(screen2,tfont,(132*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",nextcombo);
10661 }
10662
10663
10664 FONT *tf = font;
10665 font = tfont;
10666
10667 draw_checkbox(screen2,320,440+yofs,16,combopage_animate);
10668 textprintf_ex(screen2,tfont,320+18,440+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Animate");
10669
10670 if(buttons&2)
10671 {
10672 draw_text_button(screen2,404,426+yofs,88,42,"Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10673 }
10674
10675 if(buttons&4)
10676 {
10677 draw_text_button(screen2,494,426+yofs,88,42,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10678 }
10679
10680 font = tf;
10681
10682 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
10683 textprintf_ex(screen2,tfont,(293*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
10684 textprintf_centre_ex(screen2,tfont,(309*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
10685 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
10686
10687 int32_t w = 640;
10688 int32_t h = 480;
10689 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10690 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10691 int32_t screen_xofs=window_xofs+6;
10692 int32_t screen_yofs=window_yofs+25;
10693
10694 custom_vsync();
10695 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
10696 SCRFIX();
10697 //destroy_bitmap(buf);
10698 }
10699
10700 void sel_combo(int32_t &tile, int32_t &tile2, int32_t s, bool cols)
10701 {
10702 int32_t page = tile&0xFF00;
10703 tile &= 0xFF;
10704
10705 if(!cols)
10706 tile += s;
10707 else
10708 {
10709 if(s==-COMBOS_PER_ROW)
10710 tile-=4;
10711
10712 if(s==COMBOS_PER_ROW)
10713 tile+=4;
10714
10715 if(s==-1)
10716 tile-=1;
10717
10718 if(s==1)
10719 tile+=1;
10720 }
10721
10722 /*
10723 if(s==1)
10724 {
10725 if((tile&3)==3)
10726 tile+=48;
10727 else
10728 ++tile;
10729 }
10730 if(s==-1)
10731 {
10732 if((tile&3)==0)
10733 tile-=48;
10734 else
10735 --tile;
10736 }
10737 }
10738 */
10739 bound(tile,0,255);
10740 tile += page;
10741
10742 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
10743 tile2 = tile;
10744 }
10745
10746 void draw_combo_list_window()
10747 {
10748 int32_t window_xofs=0;
10749 int32_t window_yofs=0;
10750 int32_t w = 640;
10751 int32_t h = 480;
10752
10753 window_xofs=(zq_screen_w-w-12)>>1;
10754 window_yofs=(zq_screen_h-h-25-6)>>1;
10755 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
10756 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
10757 FONT *oldfont = font;
10758 font = get_zc_font(font_lfont);
10759 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Combo", true);
10760 font=oldfont;
10761 }
10762
10763
10764 static int32_t _selected_combo=-1, _selected_cset=-1;
10765 bool select_combo_2(int32_t &cmb,int32_t &cs)
10766 {
10767 popup_zqdialog_start();
10768 reset_combo_animations();
10769 reset_combo_animations2();
10770 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
10771 // static int32_t cmb=0;
10772 int32_t page=cmb>>8;
10773 int32_t tile2=cmb;
10774 int32_t done=0;
10775 int32_t tile_clicked=-1;
10776 int32_t t2;
10777 int32_t copy=-1;
10778 int32_t copycnt=0;
10779
10780 position_mouse_z(0);
10781
10782 go();
10783 int32_t w = 640;
10784 int32_t h = 480;
10785 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10786 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10787 int32_t screen_xofs=window_xofs+6;
10788 int32_t screen_yofs=window_yofs+25;
10789 int32_t panel_yofs=3;
10790 int32_t mul = 2;
10791 FONT *tfont = get_zc_font(font_lfont_l);
10792
10793 draw_combo_list_window();
10794 draw_combos(page,cs,combo_cols);
10795 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
10796
10797 while(gui_mouse_b())
10798 {
10799 /* do nothing */
10800 rest(1);
10801 }
10802
10803 bool bdown=false;
10804 int32_t f=0;
10805 int otl = cmb, otl2 = tile2;
10806
10807 do
10808 {
10809 HANDLE_CLOSE_ZQDLG();
10810 if(exiting_program) break;
10811 rest(4);
10812 bool redraw=false;
10813
10814 if(mouse_z<0)
10815 {
10816 if(page<COMBO_PAGES-1)
10817 {
10818 ++page;
10819 cmb=tile2=(page<<8)+(cmb&0xFF);
10820 }
10821
10822 position_mouse_z(0);
10823 redraw=true;
10824 }
10825 else if(mouse_z>0)
10826 {
10827 if(page>0)
10828 {
10829 --page;
10830 cmb=tile2=(page<<8)+(cmb&0xFF);
10831 }
10832
10833 position_mouse_z(0);
10834 redraw=true;
10835 }
10836
10837 if(keypressed())
10838 {
10839 switch(readkey()>>8)
10840 {
10841 case KEY_DEL:
10842 cmb=0;
10843 done=2;
10844 break;
10845
10846 case KEY_ENTER_PAD:
10847 case KEY_ENTER:
10848 done=2;
10849 break;
10850
10851 case KEY_ESC:
10852 done=1;
10853 break;
10854
10855 case KEY_F1:
10856 onHelp();
10857 break;
10858
10859 case KEY_SPACE:
10860 combo_cols=!combo_cols;
10861 redraw=true;
10862 break;
10863
10864 case KEY_EQUALS:
10865 case KEY_PLUS_PAD:
10866 cs = (cs<13) ? cs+1:0;
10867 redraw=true;
10868 break;
10869
10870 case KEY_MINUS:
10871 case KEY_MINUS_PAD:
10872 cs = (cs>0) ? cs-1:13;
10873 redraw=true;
10874 break;
10875
10876 case KEY_UP:
10877 sel_combo(cmb,tile2,-COMBOS_PER_ROW,combo_cols);
10878 redraw=true;
10879 break;
10880
10881 case KEY_DOWN:
10882 sel_combo(cmb,tile2,COMBOS_PER_ROW,combo_cols);
10883 redraw=true;
10884 break;
10885
10886 case KEY_LEFT:
10887 sel_combo(cmb,tile2,-1,combo_cols);
10888 redraw=true;
10889 break;
10890
10891 case KEY_RIGHT:
10892 sel_combo(cmb,tile2,1,combo_cols);
10893 redraw=true;
10894 break;
10895
10896 case KEY_PGUP:
10897 if(page>0)
10898 {
10899 --page;
10900 cmb=tile2=(page<<8)+(cmb&0xFF);
10901 }
10902
10903 redraw=true;
10904 break;
10905
10906 case KEY_PGDN:
10907 if(page<COMBO_PAGES-1)
10908 {
10909 ++page;
10910 cmb=tile2=(page<<8)+(cmb&0xFF);
10911 }
10912
10913 redraw=true;
10914 break;
10915
10916 case KEY_P:
10917 {
10918 int32_t choosepage=getnumber("Goto Page", (PreFillComboEditorPage?page:0));
10919
10920 if(!cancelgetnum)
10921 page=(zc_min(choosepage,COMBO_PAGES-1));
10922
10923 cmb=tile2=(page<<8)+(cmb&0xFF);
10924 redraw=true;
10925 break;
10926 }
10927 }
10928
10929 clear_keybuf();
10930 }
10931
10932 if(gui_mouse_b()&1)
10933 {
10934 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
10935 {
10936 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
10937 {
10938 done=1;
10939 }
10940 }
10941
10942 int32_t x=gui_mouse_x()-screen_xofs;
10943 int32_t y=gui_mouse_y()-screen_yofs;
10944
10945 if(y>=0 && y<208*mul)
10946 {
10947 x=zc_min(zc_max(x,0),(320*mul)-1);
10948 int32_t t;
10949
10950 if(!combo_cols)
10951 {
10952 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
10953 }
10954 else
10955 {
10956 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10957 }
10958
10959 bound(t,0,255);
10960 t+=page<<8;
10961 cmb=tile2=t;
10962
10963 if(tile_clicked!=t)
10964 {
10965 dclick_status=DCLICK_NOT;
10966 }
10967 else if(dclick_status == DCLICK_AGAIN)
10968 {
10969 while(gui_mouse_b())
10970 {
10971 /* do nothing */
10972 }
10973
10974 if(!combo_cols)
10975 {
10976 t2 = (y>>5)*COMBOS_PER_ROW + (x>>5);
10977 }
10978 else
10979 {
10980 t2 = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10981 }
10982
10983 if(t2!=t)
10984 {
10985 dclick_status=DCLICK_NOT;
10986 }
10987 else
10988 {
10989 done=2;
10990 }
10991 }
10992
10993 tile_clicked=t;
10994 }
10995 else if(y>=(208*mul) && x>(300*mul) && !bdown)
10996 {
10997 if(y<(224*mul)+panel_yofs && page>0)
10998 {
10999 --page;
11000 redraw=true;
11001 }
11002
11003 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
11004 {
11005 ++page;
11006 redraw=true;
11007 }
11008
11009 bdown=true;
11010 }
11011
11012 if(!bdown && isinRect(x,y,(247*mul),(213*mul),((247+44)*mul),((213+21)*mul)))
11013 {
11014 FONT *tf = font;
11015 font = tfont;
11016
11017 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11018 {
11019 done=2;
11020 }
11021
11022 font = tf;
11023 }
11024 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11025 {
11026 FONT *tf = font;
11027 font = tfont;
11028
11029 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11030 combopage_animate = combopage_animate ? 0 : 1;
11031 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11032 redraw = true;
11033
11034 font = tf;
11035 }
11036
11037 bdown=true;
11038 }
11039
11040 bool r_click = false;
11041
11042 if(gui_mouse_b()&2 && !bdown)
11043 {
11044 int32_t x=gui_mouse_x()+screen_xofs;
11045 int32_t y=gui_mouse_y()+screen_yofs;
11046
11047 if(y>=0 && y<208*mul)
11048 {
11049 x=zc_min(zc_max(x,0),(320*mul)-1);
11050 int32_t t;
11051
11052 if(!combo_cols)
11053 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
11054 else
11055 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11056
11057 bound(t,0,255);
11058 t+=page<<8;
11059
11060 if(t<zc_min(cmb,tile2) || t>zc_max(cmb,tile2))
11061 cmb=tile2=t;
11062 }
11063
11064 bdown = r_click = true;
11065 f=8;
11066 }
11067
11068 if(gui_mouse_b()==0)
11069 bdown=false;
11070
11071 if((f%8) || InvalidBG == 1)
11072 redraw = true;
11073 if(otl != cmb || otl2 != tile2)
11074 {
11075 otl = cmb;
11076 otl2 = tile2;
11077 redraw = true;
11078 }
11079
11080 if(redraw || combopage_animate)
11081 draw_combos(page,cs,combo_cols);
11082
11083 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
11084
11085 if(f&8)
11086 {
11087 int32_t x,y;
11088
11089 for(int32_t i=zc_min(cmb,tile2); i<=zc_max(cmb,tile2); i++)
11090 {
11091 if((i>>8)==page)
11092 {
11093 int32_t t=i&255;
11094
11095 if(!combo_cols)
11096 {
11097 x=(t%COMBOS_PER_ROW)<<5;
11098 y=(t/COMBOS_PER_ROW)<<5;
11099 }
11100 else
11101 {
11102 x=((t&3) + ((t/52)<<2)) << 5;
11103 y=((t%52)>>2) << 5;
11104 }
11105
11106 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11107 }
11108 }
11109
11110 SCRFIX();
11111 }
11112
11113 ++f;
11114
11115 }
11116 while(!done);
11117
11118 while(gui_mouse_b())
11119 {
11120 /* do nothing */
11121 rest(1);
11122 }
11123
11124 comeback();
11125 setup_combo_animations();
11126 setup_combo_animations2();
11127
11128 bool ret = done==2;
11129 if(ret)
11130 {
11131 _selected_combo = cmb;
11132 _selected_cset = cs;
11133 }
11134
11135 popup_zqdialog_end();
11136 return ret;
11137 }
11138
11139 bool select_combo_3(int32_t &cmb,int32_t &cs)
11140 {
11141 if(_selected_combo < 0)
11142 {
11143 _selected_combo = Combo;
11144 _selected_cset = CSet;
11145 }
11146 cmb = _selected_combo;
11147 cs = _selected_cset;
11148 return select_combo_2(cmb,cs);
11149 }
11150
11151 bool advpaste(int32_t tile, int32_t tile2, int32_t copy)
11152 {
11153 static bitstring pasteflags;
11154 static const vector<CheckListInfo> advp_names =
11155 {
11156 { "Tile" },
11157 { "CSet2" },
11158 { "Solidity" },
11159 { "Animation" },
11160 { "Type" },
11161 { "Inherent Flag" },
11162 { "Attribytes" },
11163 { "Attrishorts" },
11164 { "Attributes" },
11165 { "Flags", "The 16 Flags on the 'Flags' tab" },
11166 { "Gen. Flags", "The 2 'General Flags' on the 'Flags' tab" },
11167 { "Label" },
11168 { "Script" },
11169 { "Effect" },
11170 { "Triggers Tab" },
11171 { "Lifting Tab" },
11172 { "Gen: Movespeed", "The Movespeed related values from the 'General' tab" },
11173 { "Gen: SFX", "The SFX related values from the 'General' tab" },
11174 { "Gen: Sprites", "The Sprites related values from the 'General' tab" },
11175 };
11176 if(!call_checklist_dialog("Advanced Paste",advp_names,pasteflags))
11177 return false;
11178
11179 //Paste to each combo in the range
11180 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11181 {
11182 combobuf[i].advpaste(combobuf[copy], pasteflags);
11183 }
11184
11185 if(pasteflags.get(CMB_ADVP_TILE)) //reset animations if needed
11186 {
11187 setup_combo_animations();
11188 setup_combo_animations2();
11189 }
11190
11191 return true;
11192 }
11193
11194 int32_t combo_screen(int32_t pg, int32_t tl)
11195 {
11196 popup_zqdialog_start();
11197 reset_combo_animations();
11198 reset_combo_animations2();
11199 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
11200 static int32_t tile=0;
11201 static int32_t page=0;
11202
11203 if(pg>-1)
11204 page = pg;
11205
11206 if(tl>-1)
11207 tile = tl;
11208
11209 int32_t tile2=tile;
11210 int32_t done=0;
11211 int32_t cs = CSet;
11212 int32_t copy=-1;
11213 int32_t copycnt=0;
11214
11215 int32_t tile_clicked=-1;
11216 int32_t t2;
11217
11218 bool masscopy;
11219
11220 go();
11221 int32_t w = 640;
11222 int32_t h = 480;
11223 int32_t window_xofs=(zq_screen_w-w-12)>>1;
11224 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
11225 int32_t screen_xofs=window_xofs+6;
11226 int32_t screen_yofs=window_yofs+25;
11227 int32_t panel_yofs=3;
11228 int32_t mul = 2;
11229 FONT *tfont = get_zc_font(font_lfont_l);
11230
11231 draw_combo_list_window();
11232 draw_combos(page,cs,combo_cols);
11233 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11234 go_combos();
11235 position_mouse_z(0);
11236
11237 while(gui_mouse_b())
11238 {
11239 /* do nothing */
11240 }
11241
11242 bool bdown=false;
11243 int32_t f=0;
11244 int otl = tile, otl2 = tile2;
11245
11246 do
11247 {
11248 HANDLE_CLOSE_ZQDLG();
11249 if(exiting_program) break;
11250 rest(4);
11251 bool redraw=false;
11252
11253 if(mouse_z<0)
11254 {
11255 if(page<COMBO_PAGES-1)
11256 {
11257 ++page;
11258 tile=tile2=(page<<8)+(tile&0xFF);
11259 }
11260
11261 position_mouse_z(0);
11262 redraw=true;
11263 }
11264 else if(mouse_z>0)
11265 {
11266 if(page>0)
11267 {
11268 --page;
11269 tile=tile2=(page<<8)+(tile&0xFF);
11270 }
11271
11272 position_mouse_z(0);
11273 redraw=true;
11274 }
11275
11276 if(keypressed())
11277 {
11278 switch(readkey()>>8)
11279 {
11280 case KEY_ENTER_PAD:
11281 case KEY_ENTER:
11282 done=2;
11283 break;
11284
11285 case KEY_ESC:
11286 done=1;
11287 break;
11288
11289 case KEY_F1:
11290 onHelp();
11291 break;
11292
11293 case KEY_SPACE:
11294 combo_cols=!combo_cols;
11295 redraw=true;
11296 break;
11297
11298 case KEY_EQUALS:
11299 case KEY_PLUS_PAD:
11300 if(CHECK_CTRL_CMD)
11301 {
11302 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11303 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11304 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11305
11306 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11307 {
11308 combobuf[i].set_tile(wrap(combobuf[i].o_tile + amnt,
11309 0, NEWMAXTILES-1));
11310 }
11311
11312 setup_combo_animations();
11313 redraw=true;
11314 }
11315 else
11316 {
11317 cs = (cs<13) ? cs+1:0;
11318 redraw=true;
11319 }
11320
11321 break;
11322
11323 case KEY_MINUS:
11324 case KEY_MINUS_PAD:
11325 if(CHECK_CTRL_CMD)
11326 {
11327 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11328 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11329 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11330
11331 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11332 {
11333 combobuf[i].set_tile(wrap(combobuf[i].o_tile - amnt,
11334 0, NEWMAXTILES-1));
11335 }
11336
11337 setup_combo_animations();
11338 redraw=true;
11339 }
11340 else
11341 {
11342 cs = (cs>0) ? cs-1:13;
11343 redraw=true;
11344 }
11345
11346 break;
11347
11348 case KEY_UP:
11349 sel_combo(tile,tile2,-COMBOS_PER_ROW,combo_cols);
11350 redraw=true;
11351 break;
11352
11353 case KEY_DOWN:
11354 sel_combo(tile,tile2,COMBOS_PER_ROW,combo_cols);
11355 redraw=true;
11356 break;
11357
11358 case KEY_LEFT:
11359 sel_combo(tile,tile2,-1,combo_cols);
11360 redraw=true;
11361 break;
11362
11363 case KEY_RIGHT:
11364 sel_combo(tile,tile2,1,combo_cols);
11365 redraw=true;
11366 break;
11367
11368 case KEY_PGUP:
11369 if(page>0)
11370 {
11371 --page;
11372 tile=tile2=(page<<8)+(tile&0xFF);
11373 }
11374
11375 redraw=true;
11376 break;
11377
11378 case KEY_PGDN:
11379 if(page<COMBO_PAGES-1)
11380 {
11381 ++page;
11382 tile=tile2=(page<<8)+(tile&0xFF);
11383 }
11384
11385 redraw=true;
11386 break;
11387
11388 case KEY_A:
11389 {
11390 tile=(page<<8);
11391 tile2=(page<<8)+(0xFF);
11392 }
11393
11394 redraw=true;
11395 break;
11396
11397 case KEY_P:
11398 {
11399 int32_t choosepage = getnumber("Goto Page", (PreFillComboEditorPage?page:0));
11400
11401 if(!cancelgetnum)
11402 page=(zc_min(choosepage,COMBO_PAGES-1));
11403
11404 tile=tile2=(page<<8)+(tile&0xFF);
11405 redraw=true;
11406 }
11407 break;
11408
11409 case KEY_U:
11410 comeback_combos();
11411 redraw=true;
11412 break;
11413
11414 case KEY_E:
11415 go_combos();
11416 edit_combo(tile,false,cs);
11417 redraw=true;
11418 setup_combo_animations();
11419 setup_combo_animations2();
11420 break;
11421
11422 case KEY_C:
11423 go_combos();
11424 copy=zc_min(tile,tile2);
11425 copycnt=abs(tile-tile2)+1;
11426 redraw=true;
11427 break;
11428
11429 case KEY_H:
11430 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11431 {
11432 combobuf[i].flip^=1;
11433 byte w2=combobuf[i].walk;
11434 combobuf[i].walk=((w2& ~0x33)>>2 | (w2&0x33)<<2);
11435 w2=combobuf[i].csets;
11436 combobuf[i].csets= (((w2& ~0x50)>>1 | (w2&0x50)<<1) & ~0x0F) | (w2 & 0x0F);
11437 }
11438
11439 redraw=true;
11440 saved=false;
11441 break;
11442
11443 case KEY_M:
11444 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
11445 {
11446 move_combos(tile,tile2,copy,copycnt);
11447 saved=false;
11448 }
11449
11450 redraw=true;
11451 break;
11452
11453 case KEY_S:
11454 tile=tile2=zc_min(tile,tile2);
11455
11456 if(copy>=0 && tile!=copy)
11457 {
11458 go_combos();
11459
11460 for(int32_t i=0; i<copycnt; i++)
11461 {
11462 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11463 }
11464
11465 saved=false;
11466 setup_combo_animations();
11467 setup_combo_animations2();
11468 }
11469
11470 redraw=true;
11471 copy=-1;
11472 break;
11473
11474 case KEY_V:
11475 if((CHECK_CTRL_CMD) && copy != -1)
11476 {
11477 if(advpaste(tile, tile2, copy))
11478 {
11479 saved=false;
11480 redraw=true;
11481 copy=-1;
11482 }
11483
11484 break;
11485 }
11486
11487 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11488
11489 if(copy==-1)
11490 {
11491 go_combos();
11492
11493 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11494 {
11495 combobuf[i].flip^=2;
11496 byte w2=combobuf[i].walk;
11497 combobuf[i].walk=(w2&0x55)<<1 | (w2& ~0x55)>>1;
11498 w2=combobuf[i].csets;
11499 combobuf[i].csets= (((w2&0x30)<<2 | (w2& ~0x30)>>2) & ~0x0F) | (w2 & 0x0F);
11500 }
11501
11502 saved=false;
11503 }
11504 else
11505 {
11506 go_combos();
11507 copy_combos(tile,tile2,copy,copycnt,masscopy);
11508 setup_combo_animations();
11509 setup_combo_animations2();
11510 saved=false;
11511 }
11512
11513 redraw=true;
11514 break;
11515 case KEY_R:
11516 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11517 {
11518 combobuf[i].flip = rotate_value(combobuf[i].flip);
11519 combobuf[i].walk = rotate_walk(combobuf[i].walk);
11520 combobuf[i].csets = rotate_cset(combobuf[i].csets);
11521 }
11522
11523 redraw=true;
11524 saved=false;
11525 break;
11526
11527 case KEY_I:
11528 {
11529 // rev.1509; Can now insert/remove all selected combos
11530 int32_t z=tile;
11531 int32_t numSelected = abs(tile-tile2) + 1;
11532 tile=zc_min(tile,tile2);
11533 tile2=MAXCOMBOS;
11534 copy = tile + numSelected; // copy=tile+1;
11535 copycnt = MAXCOMBOS-tile-numSelected; // copycnt=MAXCOMBOS-tile;
11536
11537 if(key[KEY_LSHIFT]||key[KEY_RSHIFT])
11538 {
11539 char buf[64];
11540
11541 if(numSelected>1)
11542 sprintf(buf,"Remove combos %d - %d?",tile, copy-1);
11543 else
11544 sprintf(buf,"Remove combo %d?",tile);
11545
11546 if(jwin_alert("Confirm Remove",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11547 {
11548 move_combos(tile,tile2,copy, copycnt);
11549 //don't allow the user to undo; quest combo references are incorrect -DD
11550 go_combos();
11551 redraw=true;
11552 saved=false;
11553 }
11554 }
11555 else
11556 {
11557 char buf[64];
11558
11559 if(numSelected>1)
11560 sprintf(buf,"Insert %d blank combos?",numSelected);
11561 else
11562 sprintf(buf,"Insert a blank combo?");
11563
11564 if(jwin_alert("Confirm Insert",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11565 {
11566 move_combos(copy,tile2,tile, copycnt);
11567 go_combos();
11568 redraw=true;
11569 saved=false;
11570 }
11571 }
11572
11573 copy=-1;
11574 tile2=tile=z;
11575 }
11576 break;
11577
11578 case KEY_DEL:
11579 {
11580 char buf[40];
11581
11582 if(tile==tile2)
11583 {
11584 sprintf(buf,"Delete combo %d?",tile);
11585 }
11586 else
11587 {
11588 sprintf(buf,"Delete combos %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
11589 }
11590
11591 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11592 {
11593 go_combos();
11594
11595 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11596 {
11597 clear_combo(i);
11598 }
11599
11600 tile=tile2=zc_min(tile,tile2);
11601 redraw=true;
11602 saved=false;
11603 setup_combo_animations();
11604 setup_combo_animations2();
11605 }
11606 }
11607 break;
11608 }
11609
11610 clear_keybuf();
11611 }
11612
11613 if(gui_mouse_b()&1)
11614 {
11615 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
11616 {
11617 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
11618 {
11619 done=1;
11620 }
11621 }
11622
11623 int32_t x=gui_mouse_x()-screen_xofs;
11624 int32_t y=gui_mouse_y()-screen_yofs;
11625
11626 if(y>=0 && y<(208*mul))
11627 {
11628 x=zc_min(zc_max(x,0),(320*mul)-1);
11629 int32_t t;
11630
11631 if(!combo_cols)
11632 {
11633 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
11634 }
11635 else
11636 {
11637 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11638 }
11639
11640 bound(t,0,255);
11641 t+=page<<8;
11642
11643 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
11644 {
11645 tile2=t;
11646 }
11647 else
11648 {
11649 tile=tile2=t;
11650 }
11651
11652 if(tile_clicked!=t)
11653 {
11654 dclick_status=DCLICK_NOT;
11655 }
11656 else if(dclick_status == DCLICK_AGAIN)
11657 {
11658 while(gui_mouse_b())
11659 {
11660 /* do nothing */
11661 rest(1);
11662 }
11663
11664 if(!combo_cols)
11665 {
11666 t2 = (y>>4)*COMBOS_PER_ROW + (x>>4);
11667 }
11668 else
11669 {
11670 t2 = ((x>>6)*52) + ((x>>4)&3) + ((y>>4)<<2);
11671 }
11672
11673 bound(t2,0,255);
11674 t2+=page<<8;
11675
11676 if(t2!=t)
11677 {
11678 dclick_status=DCLICK_NOT;
11679 }
11680 else
11681 {
11682 go_combos();
11683 edit_combo(tile,false,cs);
11684 redraw=true;
11685 setup_combo_animations();
11686 setup_combo_animations2();
11687 }
11688 }
11689
11690 tile_clicked=t;
11691 }
11692 else if(x>(300*mul) && !bdown)
11693 {
11694 if(y<(224*mul)+panel_yofs && page>0)
11695 {
11696 --page;
11697 redraw=true;
11698 }
11699
11700 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
11701 {
11702 ++page;
11703 redraw=true;
11704 }
11705
11706 bdown=true;
11707 }
11708
11709 if(!bdown && isinRect(x,y,(202*mul),(213*mul)+panel_yofs,(202+44)*mul,(213+21)*mul))
11710 {
11711 FONT *tf = font;
11712 font = tfont;
11713
11714 if(do_text_button((202*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Edit"))
11715 {
11716 font = tf;
11717 edit_combo(tile,false,cs);
11718 redraw=true;
11719 }
11720
11721 font = tf;
11722 }
11723 else if(!bdown && isinRect(x,y,(247*mul),(213*mul)+panel_yofs,(247+44)*mul,(213+21)*mul))
11724 {
11725 FONT *tf = font;
11726 font = tfont;
11727
11728 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11729 {
11730 done=1;
11731 }
11732
11733 font = tf;
11734 }
11735 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11736 {
11737 FONT *tf = font;
11738 font = tfont;
11739
11740 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11741 combopage_animate = combopage_animate ? 0 : 1;
11742 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11743 redraw = true;
11744
11745 font = tf;
11746 }
11747
11748 bdown=true;
11749 }
11750
11751 bool r_click = false;
11752
11753 if(gui_mouse_b()&2 && !bdown)
11754 {
11755 int32_t x=gui_mouse_x()-screen_xofs;
11756 int32_t y=gui_mouse_y()-screen_yofs;
11757
11758 if(y>=0 && y<(208*mul))
11759 {
11760 x=zc_min(zc_max(x,0),(320*mul)-1);
11761 int32_t t;
11762
11763 if(!combo_cols)
11764 {
11765 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
11766 }
11767 else
11768 {
11769 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11770 }
11771
11772 bound(t,0,255);
11773 t+=page<<8;
11774
11775 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
11776 {
11777 tile=tile2=t;
11778 }
11779 }
11780
11781 bdown = r_click = true;
11782 f=8;
11783 }
11784
11785 REDRAW:
11786
11787 if(gui_mouse_b()==0)
11788 bdown=false;
11789
11790 if((f%8) || InvalidBG == 1)
11791 redraw = true;
11792 if(otl != tile || otl2 != tile2)
11793 {
11794 otl = tile;
11795 otl2 = tile2;
11796 redraw = true;
11797 }
11798
11799 if(redraw || combopage_animate)
11800 draw_combos(page,cs,combo_cols);
11801
11802 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11803
11804 if(f&8)
11805 {
11806 int32_t x,y;
11807
11808 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11809 {
11810 if((i>>8)==page)
11811 {
11812 int32_t t=i&255;
11813
11814 if(!combo_cols)
11815 {
11816 x=(t%COMBOS_PER_ROW)<<5;
11817 y=(t/COMBOS_PER_ROW)<<5;
11818 }
11819 else
11820 {
11821 x=((t&3) + ((t/52)<<2)) << 5;
11822 y=((t%52)>>2) << 5;
11823 }
11824
11825 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11826 }
11827 }
11828
11829 SCRFIX();
11830 }
11831
11832 ++f;
11833
11834 //Seriously? There is duplicate code for the r-click menu? -Gleeok
11835 if(r_click)
11836 {
11837 NewMenu rcmenu
11838 {
11839 { "Copy", [&]()
11840 {
11841 go_combos();
11842 copy=zc_min(tile,tile2);
11843 copycnt=abs(tile-tile2)+1;
11844 } },
11845 { "Paste", [&]()
11846 {
11847 if((CHECK_CTRL_CMD) && copy != -1)
11848 {
11849 if(advpaste(tile, tile2, copy))
11850 {
11851 saved=false;
11852 redraw=true;
11853 copy=-1;
11854 }
11855 return;
11856 }
11857
11858 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11859
11860 if(copy>-1)
11861 {
11862 go_combos();
11863 copy_combos(tile,tile2,copy,copycnt,masscopy);
11864 setup_combo_animations();
11865 setup_combo_animations2();
11866 saved=false;
11867 }
11868 } },
11869 { "Adv. Paste", [&]()
11870 {
11871 if(copy > -1)
11872 {
11873 if(advpaste(tile, tile2, copy))
11874 {
11875 saved=false;
11876 redraw=true;
11877 copy=-1;
11878 }
11879 }
11880 } },
11881 { "Swap", [&]()
11882 {
11883 tile=tile2=zc_min(tile,tile2);
11884
11885 if(copy>=0 && tile!=copy)
11886 {
11887 go_combos();
11888
11889 for(int32_t i=0; i<copycnt; i++)
11890 {
11891 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11892 }
11893
11894 saved=false;
11895 setup_combo_animations();
11896 setup_combo_animations2();
11897 }
11898 copy=-1;
11899 } },
11900 { "Delete", [&]()
11901 {
11902 string msg;
11903
11904 if(tile==tile2)
11905 msg = fmt::format("Delete combo {}?",tile);
11906 else
11907 msg = fmt::format("Delete combos {}-{}?",zc_min(tile,tile2),zc_max(tile,tile2));
11908 bool didconfirm = false;
11909 AlertDialog("Confirm Delete",msg,
11910 [&](bool ret,bool)
11911 {
11912 if(ret)
11913 didconfirm = true;
11914 }).show();
11915 if(didconfirm)
11916 {
11917 go_combos();
11918
11919 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11920 clear_combo(i);
11921
11922 tile=tile2=zc_min(tile,tile2);
11923 saved=false;
11924 }
11925 } },
11926 {},
11927 { "Edit", [&]()
11928 {
11929 go_combos();
11930 edit_combo(tile,false,cs);
11931 } },
11932 { "Insert", [&]()
11933 {
11934 int z = tile;
11935 int count = abs(tile-tile2)+1;
11936 tile = zc_min(tile,tile2);
11937 tile2 = MAXCOMBOS;
11938 copy = tile+count;
11939 copycnt = MAXCOMBOS-tile-count;
11940
11941 string msg;
11942
11943 if(count>1)
11944 msg = fmt::format("Insert combos {} - {}?"
11945 " This will offset all of the combos that follow!",tile, copy-1);
11946 else
11947 msg = fmt::format("Insert combo {}?"
11948 " This will offset all of the combos that follow!",tile);
11949
11950 bool didconfirm = false;
11951 AlertDialog("Confirm Insert",msg,
11952 [&](bool ret,bool)
11953 {
11954 if(ret)
11955 didconfirm = true;
11956 }).show();
11957 if(didconfirm)
11958 move_combos(copy, tile2, tile, copycnt);
11959 else return;
11960
11961 copy = -1;
11962 tile2 = tile = z;
11963
11964 //don't allow the user to undo; quest combo references are incorrect -DD
11965 go_combos();
11966 saved = false;
11967 } },
11968 { "Remove", [&]()
11969 {
11970 int z = tile;
11971 int count = abs(tile-tile2)+1;
11972 tile = zc_min(tile,tile2);
11973 tile2 = MAXCOMBOS;
11974 copy = tile+count;
11975 copycnt = MAXCOMBOS-tile-count;
11976
11977 string msg;
11978
11979 if(count>1)
11980 msg = fmt::format("Remove combos {} - {}?"
11981 " This will offset all of the combos that follow!",tile, copy-1);
11982 else
11983 msg = fmt::format("Remove combo {}?"
11984 " This will offset all of the combos that follow!",tile);
11985
11986 bool didconfirm = false;
11987 AlertDialog("Confirm Remove",msg,
11988 [&](bool ret,bool)
11989 {
11990 if(ret)
11991 didconfirm = true;
11992 }).show();
11993 if(didconfirm)
11994 move_combos(tile, tile2, copy, copycnt);
11995 else return;
11996
11997 copy = -1;
11998 tile2 = tile = z;
11999
12000 //don't allow the user to undo; quest combo references are incorrect -DD
12001 go_combos();
12002 saved = false;
12003 } },
12004 {},
12005 { "Locations", [&]()
12006 {
12007 int32_t z = Combo;
12008 Combo = tile;
12009 onComboLocationReport();
12010 Combo = z;
12011 } },
12012 };
12013 rcmenu.pop(window_mouse_x(),window_mouse_y());
12014 redraw = true;
12015 r_click = false;
12016 goto REDRAW;
12017 }
12018
12019 }
12020 while(!done);
12021
12022 while(gui_mouse_b())
12023 rest(1);
12024 comeback();
12025 setup_combo_animations();
12026 setup_combo_animations2();
12027 _selected_combo = tile;
12028 _selected_cset = cs;
12029 popup_zqdialog_end();
12030 return done-1;
12031 }
12032
12033 int32_t onCombos()
12034 {
12035 // reset_combo_animations();
12036 combo_screen(-1,-1);
12037 // setup_combo_animations();
12038 refresh(rALL);
12039 return D_O_K;
12040 }
12041
12042 int32_t d_ctile_proc(int32_t msg,DIALOG *d,int32_t c)
12043 {
12044 //these are here to bypass compiler warnings about unused arguments
12045 d=d;
12046 c=c;
12047
12048 if(msg==MSG_CLICK)
12049 {
12050 int32_t t=curr_combo.o_tile;
12051 int32_t f=curr_combo.flip;
12052
12053 if(select_tile(t,f,1,CSet,true,0,true))
12054 {
12055 curr_combo.tile=t;
12056 curr_combo.o_tile=t;
12057 curr_combo.flip=f;
12058 return D_REDRAW;
12059 }
12060 }
12061
12062 return D_O_K;
12063 }
12064
12065 int32_t d_combo_loader(int32_t msg,DIALOG *d,int32_t c)
12066 {
12067 //these are here to bypass compiler warnings about unused arguments
12068 c=c;
12069
12070 if(msg==MSG_DRAW)
12071 {
12072 FONT *f = get_zc_font(font_lfont_l);
12073 textprintf_ex(screen,f,d->x,d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Tile:");
12074 textprintf_ex(screen,f,d->x+((1.5)*36),d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.o_tile);
12075 textprintf_ex(screen,f,d->x,d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
12076 textprintf_ex(screen,f,d->x+((1.5)*36),d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.flip);
12077 textprintf_ex(screen,f,d->x,d->y+(36),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet2:");
12078 }
12079
12080 return D_O_K;
12081 }
12082
12083 int32_t click_d_ctile_proc()
12084 {
12085 d_ctile_proc(MSG_CLICK,NULL,0);
12086 return D_REDRAW;
12087 }
12088
12089 int32_t click_d_combo_proc();
12090
12091 const char *comboscriptdroplist(int32_t index, int32_t *list_size)
12092 {
12093 if(index<0)
12094 {
12095 *list_size = bidcomboscripts_cnt;
12096 return NULL;
12097 }
12098
12099 return bidcomboscripts[index].first.c_str();
12100 }
12101 9 ListData comboscript_list(comboscriptdroplist, &font);
12102
12103 bool call_combo_editor(int32_t);
12104 bool edit_combo(int32_t c,bool freshen,int32_t cs)
12105 {
12106 FONT* ofont = font;
12107 //CSet = cs;
12108 reset_combo_animations();
12109 reset_combo_animations2();
12110 bool edited = call_combo_editor(c);
12111 font = ofont;
12112
12113 if(freshen)
12114 {
12115 refresh(rALL);
12116 }
12117
12118 setup_combo_animations();
12119 setup_combo_animations2();
12120
12121 return edited;
12122 }
12123
12124 int32_t d_itile_proc(int32_t msg,DIALOG *d,int32_t)
12125 {
12126 switch(msg)
12127 {
12128 case MSG_CLICK:
12129 {
12130 int32_t cs = d->d2;
12131 int32_t f = 0;
12132
12133 if(select_tile(d->d1,f,1,cs,true))
12134 {
12135 int32_t ok=1;
12136
12137 if(newtilebuf[d->d1].format==tf8Bit)
12138 jwin_alert("Warning",
12139 "You have selected an 8-bit tile.",
12140 "It will not be drawn correctly",
12141 "on the file select screen.",
12142 "&OK",NULL,'o',0,get_zc_font(font_lfont));
12143
12144 return D_REDRAW;
12145 }
12146 }
12147 break;
12148
12149 case MSG_DRAW:
12150 d->w = 32+4;
12151 d->h = 32+4;
12152
12153 BITMAP *buf = create_bitmap_ex(8,16,16);
12154 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12155
12156 if(buf && bigbmp)
12157 {
12158 clear_bitmap(buf);
12159 overtile16(buf,d->d1,0,0,d->fg,0);
12160 stretch_blit(buf, bigbmp, 0,0, 16, 16, 2, 2, d->w-4, d->h-4);
12161 destroy_bitmap(buf);
12162 jwin_draw_frame(bigbmp,0, 0, d->w,d->h, FR_DEEP);
12163 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12164 destroy_bitmap(bigbmp);
12165 }
12166
12167 break;
12168 }
12169
12170 return D_O_K;
12171 }
12172
12173 static DIALOG icon_dlg[] =
12174 {
12175 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
12176 { jwin_win_proc, 70, 70, 170, 104, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Game Icons", NULL, NULL },
12177 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
12178 { d_itile_proc, 108+3, 112, 20, 20, 0, 0, 0, 0, 0, 6, NULL, NULL, NULL },
12179 { d_itile_proc, 138+3, 112, 20, 20, 0, 0, 0, 0, 0, 7, NULL, NULL, NULL },
12180 { d_itile_proc, 168+3, 112, 20, 20, 0, 0, 0, 0, 0, 8, NULL, NULL, NULL },
12181 { d_itile_proc, 198+3, 112, 20, 20, 0, 0, 0, 0, 0, 9, NULL, NULL, NULL },
12182 { jwin_button_proc, 90, 145, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12183 { jwin_button_proc, 170, 145, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12184 { jwin_text_proc, 108+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "0", NULL, NULL },
12185 { jwin_text_proc, 138+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "1", NULL, NULL },
12186 { jwin_text_proc, 168+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "2", NULL, NULL },
12187 { jwin_text_proc, 198+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "3+", NULL, NULL },
12188 { jwin_text_proc, 88, 98, 12, 9, 0, 0, 0, 0, 0, 0, (void *) "Ring:", NULL, NULL },
12189 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12190 };
12191
12192 int32_t onIcons()
12193 {
12194 PALETTE pal;
12195 // pal = RAMpal;
12196 memcpy(pal,RAMpal,sizeof(RAMpal));
12197 icon_dlg[0].dp2=get_zc_font(font_lfont);
12198
12199 for(int32_t i=0; i<4; i++)
12200 {
12201 icon_dlg[i+2].d1 = QMisc.icons[i];
12202 icon_dlg[i+2].fg = i+6;
12203 load_cset(pal, i+6, pSprite(i+spICON1));
12204 }
12205
12206 zc_set_palette(pal);
12207
12208 large_dialog(icon_dlg);
12209
12210 int32_t ret = do_zqdialog(icon_dlg,7);
12211
12212 if(ret==6)
12213 {
12214 for(int32_t i=0; i<4; i++)
12215 {
12216 if(QMisc.icons[i] != icon_dlg[i+2].d1)
12217 {
12218 QMisc.icons[i] = icon_dlg[i+2].d1;
12219 saved=false;
12220 }
12221 }
12222 }
12223
12224 zc_set_palette(RAMpal);
12225 return D_O_K;
12226 }
12227
12228 // Identical to jwin_frame_proc, but is treated differently by large_dialog()
12229 int32_t d_comboframe_proc(int32_t msg, DIALOG *d, int32_t)
12230 {
12231 if(msg == MSG_DRAW)
12232 {
12233 jwin_draw_frame(screen, d->x, d->y, d->w, d->h, d->d1);
12234 }
12235
12236 return D_O_K;
12237 }
12238
12239 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t)
12240 {
12241 switch(msg)
12242 {
12243 case MSG_CLICK:
12244 {
12245 if((d->flags&D_NOCLICK))
12246 break;
12247
12248 int32_t ret = (d->flags & D_EXIT) ? D_CLOSE : D_O_K;
12249 int32_t combo2;
12250 int32_t cs;
12251
12252 if(CHECK_ALT) //place selected cmb/cs
12253 {
12254 if(gui_mouse_b()&1)
12255 {
12256 if(!CHECK_SHIFT)
12257 d->d1 = Combo;
12258 d->fg = CSet;
12259 }
12260
12261 return ret|D_REDRAW;
12262 }
12263 else if(gui_mouse_b()&2||nextcombo_fake_click==2) //clear to 0/0
12264 {
12265 d->d1=0;
12266 d->fg=0;
12267 return ret|D_REDRAW;
12268 }
12269 else if(gui_mouse_b()&1||nextcombo_fake_click==1) //popup combo picker
12270 {
12271 combo2=d->d1;
12272 cs=d->fg;
12273
12274 if((CHECK_CTRL_CMD ? select_combo_3 : select_combo_2)(combo2, cs))
12275 {
12276 d->d1=combo2;
12277 d->fg=cs;
12278 }
12279
12280 return ret|D_REDRAW;
12281 }
12282 else return ret|D_REDRAWME;
12283 }
12284 break;
12285
12286 case MSG_DRAW:
12287 {
12288 d->w = 32;
12289 d->h = 32;
12290
12291 BITMAP *buf = create_bitmap_ex(8,16,16);
12292 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12293
12294 if(buf && bigbmp)
12295 {
12296 clear_bitmap(buf);
12297
12298 if(d->d1==-1) // Display curr_combo instead of combobuf
12299 {
12300 newcombo hold = combobuf[0];
12301 combobuf[0] = curr_combo;
12302 putcombo(buf,0,0,0,d->fg);
12303 combobuf[0] = hold;
12304 }
12305 else if(d->d1)
12306 {
12307 putcombo(buf,0,0,d->d1,d->fg);
12308 }
12309
12310 stretch_blit(buf, bigbmp, 0,0, 16, 16, 0, 0, d->w, d->h);
12311 destroy_bitmap(buf);
12312 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12313 destroy_bitmap(bigbmp);
12314 }
12315 }
12316 break;
12317 }
12318 return D_O_K;
12319 }
12320
12321 // Hey, let's have a few hundred more lines of code, why not.
12322
12323 #define MR_4BIT 0
12324 #define MR_8BIT 1
12325
12326 static byte massRecolorSrc4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12327 static byte massRecolorDest4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12328 static word massRecolor8BitCSets=0; // Which CSets are affected? One bit each.
12329
12330 static byte massRecolorSrc8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12331 static byte massRecolorDest8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12332
12333 static int32_t massRecolorDraggedColor=-1;
12334 static int32_t massRecolorCSet;
12335 static bool massRecolorIgnoreBlank=true;
12336 static byte massRecolorType=MR_4BIT;
12337
12338 // Shows the sets of colors to replace from/to.
12339 // D_CSET: Colors are 0-15 within the current CSet rather than absolute.
12340 // D_SETTABLE: Colors can be dragged and dropped onto this one.
12341 #define D_CSET D_USER
12342 #define D_SETTABLE (D_USER<<1)
12343 int32_t d_mr_cset_proc(int32_t msg, DIALOG* d, int32_t)
12344 {
12345 BITMAP* bmp=screen;
12346 int32_t colorWidth=(d->w-4)/16;
12347 byte* colors=static_cast<byte*>(d->dp);
12348
12349 switch(msg)
12350 {
12351 case MSG_DRAW:
12352 {
12353 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12354
12355 int32_t baseColor=((d->flags&D_CSET)!=0) ? massRecolorCSet*16 : 0;
12356 for(int32_t c=0; c<16; c++)
12357 {
12358 rectfill(bmp,
12359 d->x+2+c*colorWidth, d->y+2,
12360 d->x+2+((c+1)*colorWidth)-1, d->y+2+d->h-5,
12361 baseColor+colors[c]);
12362 }
12363 }
12364 break;
12365
12366 case MSG_LPRESS:
12367 {
12368 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12369
12370 if(x >= 0 && x < 16) //sanity check!
12371 {
12372 massRecolorDraggedColor=colors[x];
12373 }
12374 }
12375 break;
12376
12377 case MSG_LRELEASE: // This isn't exactly right, but it'll do...
12378 if((d->flags&D_SETTABLE)!=0 && massRecolorDraggedColor>=0)
12379 {
12380 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12381 if(x >= 0 && x < 16) //sanity check!
12382 {
12383 colors[x]=massRecolorDraggedColor;
12384 d->flags|=D_DIRTY;
12385 }
12386 }
12387 massRecolorDraggedColor=-1;
12388 break;
12389 }
12390
12391 return D_O_K;
12392 }
12393
12394 // Used for the full palette in 8-bit mode.
12395 static int32_t d_mr_palette_proc(int32_t msg, DIALOG* d, int32_t)
12396 {
12397 BITMAP* bmp=screen;
12398 int colorWidth=(d->w-4)/16;
12399 d->h = 4+(colorWidth*14);
12400 int colorHeight=colorWidth;
12401
12402 switch(msg)
12403 {
12404 case MSG_DRAW:
12405 {
12406 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12407 for(int cset=0; cset<=13; cset++)
12408 {
12409 for(int color=0; color<16; color++)
12410 {
12411 rectfill(bmp,
12412 d->x+2+color*colorWidth,
12413 d->y+2+cset*colorHeight,
12414 d->x+2+((color+1)*colorWidth)-1,
12415 d->y+2+((cset+1)*colorHeight)-1,
12416 cset*16+color);
12417 }
12418 }
12419 }
12420 break;
12421
12422 case MSG_LPRESS:
12423 {
12424 int cset=(gui_mouse_y()-(d->y+2))/colorHeight;
12425 int color=(gui_mouse_x()-(d->x+2))/colorWidth;
12426 massRecolorDraggedColor=cset*16+color;
12427 }
12428 break;
12429 }
12430
12431 return D_O_K;
12432 }
12433
12434 static DIALOG recolor_4bit_dlg[] =
12435 {
12436 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12437 { jwin_win_proc, 0, 0, 216, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12438
12439 // 1
12440 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12441 { d_mr_cset_proc, 10, 42, 196, 16, 0, 0, 0, D_CSET, 0, 0, (void *)massRecolorSrc4Bit, NULL, NULL },
12442 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12443 { d_mr_cset_proc, 10, 70, 196, 16, 0, 0, 0, D_CSET|D_SETTABLE, 0, 0, (void *)massRecolorDest4Bit, NULL, NULL },
12444
12445 // 5
12446 { jwin_text_proc, 12, 96, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Apply to which CSets in 8-bit tiles?", NULL, NULL },
12447 { jwin_check_proc, 12, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "0", NULL, NULL },
12448 { jwin_check_proc, 36, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "1", NULL, NULL },
12449 { jwin_check_proc, 60, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "2", NULL, NULL },
12450 { jwin_check_proc, 84, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "3", NULL, NULL },
12451 { jwin_check_proc, 108, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "4", NULL, NULL },
12452 { jwin_check_proc, 132, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "5", NULL, NULL },
12453 { jwin_check_proc, 156, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "6", NULL, NULL },
12454 { jwin_check_proc, 12, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "7", NULL, NULL },
12455 { jwin_check_proc, 36, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "8", NULL, NULL },
12456 { jwin_check_proc, 60, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "9", NULL, NULL },
12457 { jwin_check_proc, 84, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "10", NULL, NULL },
12458 { jwin_check_proc, 108, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "11", NULL, NULL },
12459 { jwin_check_proc, 132, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "12", NULL, NULL },
12460 { jwin_check_proc, 156, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "13", NULL, NULL },
12461
12462 // 20
12463 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12464 { jwin_func_button_proc, 14, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset4Bit },
12465 { jwin_button_proc, 82, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 8-bit mode", NULL, NULL },
12466 { jwin_button_proc, 44, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12467 { jwin_button_proc, 112, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12468
12469 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12470 };
12471
12472 #define MR4_SRC_COLORS 2
12473 #define MR4_DEST_COLORS 4
12474 #define MR4_8BIT_EFFECT_START 6
12475 #define MR4_IGNORE_BLANK 20
12476 #define MR4_RESET 21
12477 #define MR4_SWITCH 22
12478 #define MR4_OK 23
12479 #define MR4_CANCEL 24
12480
12481 static DIALOG recolor_8bit_dlg[] =
12482 {
12483 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12484 { jwin_win_proc, 0, 0, 288, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12485
12486 // 1
12487 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12488 { d_mr_cset_proc, 10, 42, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorSrc8Bit, NULL, NULL },
12489 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12490 { d_mr_cset_proc, 10, 70, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorDest8Bit, NULL, NULL },
12491 { d_mr_palette_proc, 144, 32, 132, 150, vc(15), vc(1), 0, 0, 0, 0, (void *) NULL, NULL, NULL },
12492
12493 // 6
12494 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12495 { jwin_func_button_proc, 50, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset8Bit },
12496 { jwin_button_proc, 118, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 4-bit mode", NULL, NULL },
12497 { jwin_button_proc, 80, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12498 { jwin_button_proc, 148, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12499
12500 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12501 };
12502
12503 #define MR8_SRC_COLORS 2
12504 #define MR8_DEST_COLORS 4
12505 #define MR8_PALETTE 5
12506 #define MR8_IGNORE_BLANK 6
12507 #define MR8_RESET 7
12508 #define MR8_SWITCH 8
12509 #define MR8_OK 9
12510 #define MR8_CANCEL 10
12511
12512 static void massRecolorInit(int32_t cset)
12513 {
12514 massRecolorDraggedColor=-1;
12515 massRecolorCSet=cset;
12516
12517 recolor_4bit_dlg[0].dp2=get_zc_font(font_lfont);
12518 recolor_8bit_dlg[0].dp2=get_zc_font(font_lfont);
12519
12520 for(int32_t i=0; i<=13; i++)
12521 {
12522 if((massRecolor8BitCSets&(1<<i))!=0)
12523 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags|=D_SELECTED;
12524 else
12525 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&=~D_SELECTED;
12526 }
12527
12528 if(massRecolorIgnoreBlank)
12529 {
12530 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags|=D_SELECTED;
12531 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags|=D_SELECTED;
12532 }
12533 else
12534 {
12535 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&=~D_SELECTED;
12536 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&=~D_SELECTED;
12537 }
12538
12539 large_dialog(recolor_4bit_dlg);
12540 large_dialog(recolor_8bit_dlg);
12541
12542 // Quick fix for large_dialog() screwing these up. It's ugly. Whatever.
12543 if((recolor_4bit_dlg[MR4_DEST_COLORS].w-4)%4!=0)
12544 {
12545 recolor_4bit_dlg[MR4_SRC_COLORS].x++;
12546 recolor_4bit_dlg[MR4_SRC_COLORS].w-=2;
12547 recolor_4bit_dlg[MR4_DEST_COLORS].x++;
12548 recolor_4bit_dlg[MR4_DEST_COLORS].w-=2;
12549
12550 recolor_8bit_dlg[MR8_SRC_COLORS].x++;
12551 recolor_8bit_dlg[MR8_SRC_COLORS].w-=2;
12552 recolor_8bit_dlg[MR8_DEST_COLORS].x++;
12553 recolor_8bit_dlg[MR8_DEST_COLORS].w-=2;
12554 recolor_8bit_dlg[MR8_PALETTE].x++;
12555 recolor_8bit_dlg[MR8_PALETTE].w-=2;
12556 recolor_8bit_dlg[MR8_PALETTE].y++;
12557 recolor_8bit_dlg[MR8_PALETTE].h-=2;
12558 }
12559 }
12560
12561 static void massRecolorApplyChanges()
12562 {
12563 massRecolor8BitCSets=0;
12564 for(int32_t i=0; i<=13; i++)
12565 {
12566 if((recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&D_SELECTED)!=0)
12567 massRecolor8BitCSets|=1<<i;
12568 }
12569
12570 if(massRecolorType==MR_4BIT)
12571 massRecolorIgnoreBlank=(recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&D_SELECTED)!=0;
12572 else
12573 massRecolorIgnoreBlank=(recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&D_SELECTED)!=0;
12574 }
12575
12576 static bool massRecolorSetup(int32_t cset)
12577 {
12578 massRecolorInit(cset);
12579
12580 // Remember the current colors in case the user cancels.
12581 int32_t oldDest4Bit[16], oldSrc8Bit[16], oldDest8Bit[16];
12582 for(int32_t i=0; i<16; i++)
12583 {
12584 oldDest4Bit[i]=massRecolorDest4Bit[i];
12585 oldSrc8Bit[i]=massRecolorSrc8Bit[i];
12586 oldDest8Bit[i]=massRecolorDest8Bit[i];
12587 }
12588
12589 byte type=massRecolorType;
12590 int32_t ret;
12591 do
12592 {
12593 HANDLE_CLOSE_ZQDLG();
12594 if(exiting_program) break;
12595 if(type==MR_4BIT)
12596 {
12597 ret=do_zqdialog(recolor_4bit_dlg, MR4_OK);
12598 if(ret==MR4_SWITCH)
12599 type=MR_8BIT;
12600 }
12601 else
12602 {
12603 ret=do_zqdialog(recolor_8bit_dlg, MR8_OK);
12604 if(ret==MR8_SWITCH)
12605 type=MR_4BIT;
12606 }
12607 } while(ret==MR4_SWITCH || ret==MR8_SWITCH);
12608
12609 if(ret!=MR4_OK && ret!=MR8_OK) // Canceled
12610 {
12611 for(int32_t i=0; i<16; i++)
12612 {
12613 massRecolorDest4Bit[i]=oldDest4Bit[i];
12614 massRecolorSrc8Bit[i]=oldSrc8Bit[i];
12615 massRecolorDest8Bit[i]=oldDest8Bit[i];
12616 }
12617 return false;
12618 }
12619
12620 // OK
12621 massRecolorType=type;
12622 massRecolorApplyChanges();
12623 return true;
12624 }
12625
12626 static void massRecolorApply4Bit(int32_t tile)
12627 {
12628 byte buf[256];
12629 unpack_tile(newtilebuf, tile, 0, true);
12630
12631 if(newtilebuf[tile].format==tf4Bit)
12632 {
12633 for(int32_t i=0; i<256; i++)
12634 buf[i]=massRecolorDest4Bit[unpackbuf[i]];
12635 }
12636 else // 8-bit
12637 {
12638 for(int32_t i=0; i<256; i++)
12639 {
12640 word cset=unpackbuf[i]>>4;
12641 if((massRecolor8BitCSets&(1<<cset))!=0) // Recolor this CSet?
12642 {
12643 word color=unpackbuf[i]&15;
12644 buf[i]=(cset<<4)|massRecolorDest4Bit[color];
12645 }
12646 else
12647 buf[i]=unpackbuf[i];
12648 }
12649 }
12650
12651 pack_tile(newtilebuf, buf, tile);
12652 }
12653
12654 static void massRecolorApply8Bit(int32_t tile)
12655 {
12656 byte buf[256];
12657 unpack_tile(newtilebuf, tile, 0, true);
12658
12659 for(int32_t i=0; i<256; i++)
12660 {
12661 byte color=unpackbuf[i];
12662 for(int32_t j=0; j<16; j++)
12663 {
12664 if(massRecolorSrc8Bit[j]==color)
12665 {
12666 color=massRecolorDest8Bit[j];
12667 break;
12668 }
12669 }
12670 buf[i]=color;
12671 }
12672
12673 pack_tile(newtilebuf, buf, tile);
12674 }
12675
12676 static void massRecolorApply(int32_t tile)
12677 {
12678 if(massRecolorIgnoreBlank && blank_tile_table[tile])
12679 return;
12680
12681 if(massRecolorType==MR_4BIT)
12682 massRecolorApply4Bit(tile);
12683 else // 8-bit
12684 {
12685 if(newtilebuf[tile].format==tf4Bit)
12686 return;
12687 massRecolorApply8Bit(tile);
12688 }
12689 }
12690
12691 static void massRecolorReset4Bit()
12692 {
12693 for(int32_t i=0; i<16; i++)
12694 massRecolorDest4Bit[i]=i;
12695 recolor_4bit_dlg[MR4_DEST_COLORS].flags|=D_DIRTY;
12696 }
12697
12698 static void massRecolorReset8Bit()
12699 {
12700 for(int32_t i=0; i<16; i++)
12701 {
12702 massRecolorSrc8Bit[i]=0;
12703 massRecolorDest8Bit[i]=0;
12704 }
12705
12706 recolor_8bit_dlg[MR8_SRC_COLORS].flags|=D_DIRTY;
12707 recolor_8bit_dlg[MR8_DEST_COLORS].flags|=D_DIRTY;
12708 }
12709
12710 6 void center_zq_tiles_dialogs()
12711 {
12712 6 jwin_center_dialog(create_relational_tiles_dlg);
12713 6 jwin_center_dialog(icon_dlg);
12714 6 jwin_center_dialog(leech_dlg);
12715 6 jwin_center_dialog(move_textbox_list_dlg);
12716 6 jwin_center_dialog(recolor_4bit_dlg);
12717 6 jwin_center_dialog(recolor_8bit_dlg);
12718 6 }
12719
12720 //.ZCOMBO
12721
12722 int32_t readcombo_loop(PACKFILE* f, word section_version, newcombo& temp_combo);
12723 int32_t writecombo_loop(PACKFILE *f, word section_version, newcombo const& tmp_cmb);
12724
12725 int32_t readcombofile_old(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t zversion,
12726 dword section_version, dword section_cversion, int32_t index, int32_t count)
12727 {
12728 newcombo temp_combo;
12729 for ( int32_t tilect = 0; tilect < count; tilect++ )
12730 {
12731 temp_combo.clear();
12732 if(!p_igetw(&temp_combo.tile,f))
12733 {
12734 return 0;
12735 }
12736 temp_combo.o_tile = temp_combo.tile;
12737
12738 if(!p_getc(&temp_combo.flip,f))
12739 {
12740 return 0;
12741 }
12742
12743 if(!p_getc(&temp_combo.walk,f))
12744 {
12745 return 0;
12746 }
12747
12748 if(!p_getc(&temp_combo.type,f))
12749 {
12750 return 0;
12751 }
12752
12753 if(!p_getc(&temp_combo.csets,f))
12754 {
12755 return 0;
12756 }
12757
12758 if(!p_getc(&temp_combo.frames,f))
12759 {
12760 return 0;
12761 }
12762
12763 if(!p_getc(&temp_combo.speed,f))
12764 {
12765 return 0;
12766 }
12767
12768 if(!p_igetw(&temp_combo.nextcombo,f))
12769 {
12770 return 0;
12771 }
12772
12773 if(!p_getc(&temp_combo.nextcset,f))
12774 {
12775 return 0;
12776 }
12777
12778 if(!p_getc(&temp_combo.flag,f))
12779 {
12780 return 0;
12781 }
12782
12783 if(!p_getc(&temp_combo.skipanim,f))
12784 {
12785 return 0;
12786 }
12787
12788 if(!p_igetw(&temp_combo.nexttimer,f))
12789 {
12790 return 0;
12791 }
12792
12793 if(!p_getc(&temp_combo.skipanimy,f))
12794 {
12795 return 0;
12796 }
12797
12798 if(!p_getc(&temp_combo.animflags,f))
12799 {
12800 return 0;
12801 }
12802
12803 //2.55 starts here
12804 if ( zversion >= 0x255 )
12805 {
12806 if ( section_version >= 12 )
12807 {
12808 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12809 {
12810 if(!p_igetl(&temp_combo.attributes[q],f))
12811 {
12812 return 0;
12813 }
12814 }
12815 if(!p_igetl(&temp_combo.usrflags,f))
12816 {
12817 return 0;
12818 }
12819 for ( int32_t q = 0; q < 3; q++ )
12820 {
12821 if(!p_igetl(&temp_combo.triggerflags[q],f))
12822 {
12823 return 0;
12824 }
12825 }
12826
12827 if(!p_igetl(&temp_combo.triggerlevel,f))
12828 {
12829 return 0;
12830 }
12831 if(section_version >= 22)
12832 {
12833 if(!p_getc(&temp_combo.triggerbtn,f))
12834 {
12835 return 0;
12836 }
12837 }
12838 if(section_version < 23)
12839 {
12840 switch(temp_combo.type) //combotriggerCMBTYPEFX now required for combotype-specific effects
12841 {
12842 case cSCRIPT1: case cSCRIPT2: case cSCRIPT3: case cSCRIPT4: case cSCRIPT5:
12843 case cSCRIPT6: case cSCRIPT7: case cSCRIPT8: case cSCRIPT9: case cSCRIPT10:
12844 case cTRIGGERGENERIC: case cCSWITCH:
12845 temp_combo.triggerflags[0] |= combotriggerCMBTYPEFX;
12846 }
12847 }
12848 if(section_version >= 24)
12849 {
12850 if(!p_getc(&temp_combo.triggeritem,f))
12851 {
12852 return 0;
12853 }
12854 if(!p_getc(&temp_combo.trigtimer,f))
12855 {
12856 return 0;
12857 }
12858 }
12859 if(section_version >= 25)
12860 {
12861 if(!p_getc(&temp_combo.trigsfx,f))
12862 {
12863 return 0;
12864 }
12865 }
12866 else
12867 {
12868 switch(temp_combo.type)
12869 {
12870 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
12871 if(!(temp_combo.usrflags & cflag3))
12872 temp_combo.attribytes[3] = WAV_DOOR;
12873 temp_combo.usrflags &= ~cflag3;
12874 break;
12875 }
12876 }
12877 if(section_version < 26)
12878 {
12879 if(temp_combo.type == cARMOS)
12880 {
12881 if(temp_combo.usrflags & cflag1)
12882 temp_combo.usrflags |= cflag3;
12883 }
12884 }
12885 if(section_version >= 27)
12886 {
12887 if(!p_igetl(&temp_combo.trigchange,f))
12888 {
12889 return qe_invalid;
12890 }
12891 }
12892 else
12893 {
12894 if(temp_combo.triggerflags[0] & 0x00040000) //'next'
12895 temp_combo.trigchange = 1;
12896 else if(temp_combo.triggerflags[0] & 0x00080000) //'prev'
12897 temp_combo.trigchange = -1;
12898 else temp_combo.trigchange = 0;
12899 temp_combo.triggerflags[0] &= ~(0x00040000|0x00080000);
12900 }
12901 if(section_version >= 29)
12902 {
12903 if(!p_igetw(&temp_combo.trigprox,f))
12904 {
12905 return qe_invalid;
12906 }
12907 if(!p_getc(&temp_combo.trigctr,f))
12908 {
12909 return qe_invalid;
12910 }
12911 if(!p_igetl(&temp_combo.trigctramnt,f))
12912 {
12913 return qe_invalid;
12914 }
12915 }
12916 else
12917 {
12918 temp_combo.trigprox = 0;
12919 temp_combo.trigctr = 0;
12920 temp_combo.trigctramnt = 0;
12921 }
12922 if(section_version >= 30)
12923 {
12924 if(!p_getc(&temp_combo.triglbeam,f))
12925 {
12926 return qe_invalid;
12927 }
12928 }
12929 else temp_combo.triglbeam = 0;
12930 if(section_version >= 31)
12931 {
12932 if(!p_getc(&temp_combo.trigcschange,f))
12933 {
12934 return qe_invalid;
12935 }
12936 if(!p_igetw(&temp_combo.spawnitem,f))
12937 {
12938 return qe_invalid;
12939 }
12940 if(!p_igetw(&temp_combo.spawnenemy,f))
12941 {
12942 return qe_invalid;
12943 }
12944 if(!p_getc(&temp_combo.exstate,f))
12945 {
12946 return qe_invalid;
12947 }
12948 if(!p_igetl(&temp_combo.spawnip,f))
12949 {
12950 return qe_invalid;
12951 }
12952 if(!p_getc(&temp_combo.trigcopycat,f))
12953 {
12954 return qe_invalid;
12955 }
12956 }
12957 else
12958 {
12959 temp_combo.trigcschange = 0;
12960 temp_combo.spawnitem = 0;
12961 temp_combo.spawnenemy = 0;
12962 temp_combo.exstate = -1;
12963 temp_combo.spawnip = 0;
12964 temp_combo.trigcopycat = 0;
12965 }
12966 if(section_version >= 32)
12967 {
12968 if(!p_getc(&temp_combo.trigcooldown,f))
12969 {
12970 return qe_invalid;
12971 }
12972 }
12973 else
12974 {
12975 temp_combo.trigcooldown = 0;
12976 }
12977 char label[12];
12978 label[11] = '\0';
12979 for ( int32_t q = 0; q < 11; q++ )
12980 {
12981 if(!p_getc(&label[q],f))
12982 {
12983 return 0;
12984 }
12985 }
12986 temp_combo.label = label;
12987 }
12988 if ( section_version >= 13 )
12989 {
12990 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12991 {
12992 if(!p_getc(&temp_combo.attribytes[q],f))
12993 {
12994 return 0;
12995 }
12996 }
12997
12998 }
12999 }
13000
13001 if ( !(skip && (index+(tilect-1)) < skip) ) //is -1 still needed here?
13002 {
13003 if ( !nooverwrite || combobuf[index+tilect].is_blank() )
13004 {
13005 combobuf[index+(tilect)] = temp_combo;
13006 }
13007 }
13008 }
13009
13010 return 1;
13011 }
13012
13013 int32_t readcombofile(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t start)
13014 {
13015 dword section_version=0;
13016 dword section_cversion=0;
13017 int32_t zversion = 0;
13018 int32_t zbuild = 0;
13019
13020 if(!p_igetl(&zversion,f))
13021 {
13022 return 0;
13023 }
13024 if(!p_igetl(&zbuild,f))
13025 {
13026 return 0;
13027 }
13028 if(!p_igetw(&section_version,f))
13029 {
13030 return 0;
13031 }
13032 if(!p_igetw(&section_cversion,f))
13033 {
13034 return 0;
13035 }
13036
13037 if ( zversion > ZELDA_VERSION )
13038 {
13039 al_trace("Cannot read .zcombo packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13040 return 0;
13041 }
13042
13043 else if ( ( section_version > V_COMBOS ) || ( section_version == V_COMBOS && section_cversion > CV_COMBOS ) )
13044 {
13045 al_trace("Cannot read .zcombo packfile made using V_COMBOS (%d) subversion (%d)\n", section_version, section_cversion);
13046 return 0;
13047
13048 }
13049 else
13050 {
13051 al_trace("Reading a .zcombo packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13052 }
13053
13054 int32_t index = 0;
13055 int32_t count = 0;
13056
13057 //tile id
13058 if(!p_igetl(&index,f))
13059 {
13060 return 0;
13061 }
13062 if(start > -1) index = start;
13063 // al_trace("Reading combo: index(%d)\n", index);
13064
13065 //tile count
13066 if(!p_igetl(&count,f))
13067 {
13068 return 0;
13069 }
13070 // al_trace("Reading combo: count(%d)\n", count);
13071 reset_combo_animations();
13072 reset_combo_animations2();
13073
13074 if(section_version < 33)
13075 return readcombofile_old(f,skip,nooverwrite,zversion,section_version,section_cversion,index,count);
13076
13077 newcombo temp_combo;
13078 size_t end = index+count;
13079 for ( size_t q = index; q < end; q++ )
13080 {
13081 auto ret = readcombo_loop(f,section_version,temp_combo);
13082 if(ret) return 0;
13083
13084 if ( !(skip && q-1 < skip) )
13085 {
13086 if ( !nooverwrite || combobuf[q].is_blank() )
13087 {
13088 combobuf[q] = temp_combo;
13089 }
13090 }
13091 }
13092
13093 return 1;
13094 }
13095 int32_t readcombofile_to_location(PACKFILE *f, int32_t start, byte nooverwrite, int32_t skip)
13096 {
13097 return readcombofile(f,skip,nooverwrite,start);
13098 }
13099 int32_t writecombofile(PACKFILE *f, int32_t index, int32_t count)
13100 {
13101 dword section_version=V_COMBOS;
13102 dword section_cversion=CV_COMBOS;
13103 int32_t zversion = ZELDA_VERSION;
13104 int32_t zbuild = VERSION_BUILD;
13105
13106 if(!p_iputl(zversion,f))
13107 {
13108 return 0;
13109 }
13110 if(!p_iputl(zbuild,f))
13111 {
13112 return 0;
13113 }
13114 if(!p_iputw(section_version,f))
13115 {
13116 return 0;
13117 }
13118
13119 if(!p_iputw(section_cversion,f))
13120 {
13121 return 0;
13122 }
13123
13124 //start tile id
13125 if(!p_iputl(index,f))
13126 {
13127 return 0;
13128 }
13129
13130 //count
13131 if(!p_iputl(count,f))
13132 {
13133 return 0;
13134 }
13135 reset_combo_animations();
13136 reset_combo_animations2();
13137 size_t end = index+count;
13138 for(size_t q = index; q < end; ++q)
13139 {
13140 if(writecombo_loop(f, section_version, combobuf[q]))
13141 return 0;
13142 }
13143
13144 return 1;
13145
13146 }
13147
13148 //.ZALIAS
13149
13150
13151 //.ZALIAS
13152
13153 int32_t readcomboaliasfile(PACKFILE *f)
13154 {
13155 dword section_version=0;
13156 dword section_cversion=0;
13157 int32_t zversion = 0;
13158 int32_t zbuild = 0;
13159 word tempword = 0;
13160
13161 if(!p_igetl(&zversion,f))
13162 {
13163 return 0;
13164 }
13165 if(!p_igetl(&zbuild,f))
13166 {
13167 return 0;
13168 }
13169 if(!p_igetw(&section_version,f))
13170 {
13171 return 0;
13172 }
13173 if(!p_igetw(&section_cversion,f))
13174 {
13175 return 0;
13176 }
13177 al_trace("readoneweapon section_version: %d\n", section_version);
13178 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
13179
13180 if ( zversion > ZELDA_VERSION )
13181 {
13182 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13183 return 0;
13184 }
13185
13186 else if ( ( section_version > V_COMBOALIASES ) || ( section_version == V_COMBOALIASES && section_cversion > CV_COMBOALIASES ) )
13187 {
13188 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d) subversion (%d)\n", section_version, section_cversion);
13189 return 0;
13190
13191 }
13192 else
13193 {
13194 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13195 }
13196
13197 int32_t index = 0;
13198 int32_t count = 0;
13199 int32_t count2 = 0;
13200 byte tempcset = 0;
13201
13202 //tile id
13203 if(!p_igetl(&index,f))
13204 {
13205 return 0;
13206 }
13207 al_trace("Reading combo: index(%d)\n", index);
13208
13209 //tile count
13210 if(!p_igetl(&count,f))
13211 {
13212 return 0;
13213 }
13214 al_trace("Reading combo: count(%d)\n", count);
13215
13216 combo_alias temp_alias;
13217 memset(&temp_alias, 0, sizeof(temp_alias));
13218
13219 for ( int32_t tilect = 0; tilect < count; tilect++ )
13220 {
13221 memset(&temp_alias, 0, sizeof(temp_alias));
13222 if(!p_igetw(&temp_alias.combo,f))
13223 {
13224 return 0;
13225 }
13226
13227 if(!p_getc(&temp_alias.cset,f))
13228 {
13229 return 0;
13230 }
13231
13232
13233
13234 if(!p_igetl(&count2,f))
13235 {
13236 return 0;
13237 }
13238 al_trace("Read, Combo alias count is: %d\n", count2);
13239 if(!p_getc(&temp_alias.width,f))
13240 {
13241 return 0;
13242 }
13243
13244 if(!p_getc(&temp_alias.height,f))
13245 {
13246 return 0;
13247 }
13248
13249 if(!p_getc(&temp_alias.layermask,f))
13250 {
13251 return 0;
13252 }
13253 //These values are flexible, and may differ in size, so we delete them
13254 //and recreate them at the correct size on the pointer.
13255 temp_alias.combos.clear();
13256 temp_alias.csets.clear();
13257 for(int32_t k=0; k<count2; k++)
13258 {
13259 if(!p_igetw(&tempword,f))
13260 {
13261 return 0;
13262 }
13263 else
13264 {
13265
13266
13267 temp_alias.combos[k] = tempword;
13268 }
13269 }
13270
13271 for(int32_t k=0; k<count2; k++)
13272 {
13273 if(!p_getc(&tempcset,f))
13274 //if(!p_getc(&temp_alias.csets[k],f))
13275 {
13276 return 0;
13277 }
13278 else
13279 {
13280
13281 temp_alias.csets[k] = tempcset;
13282 }
13283 }
13284 memcpy(&combo_aliases[index+(tilect)],&temp_alias,sizeof(combo_alias));
13285 }
13286
13287 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
13288
13289
13290 return 1;
13291
13292 }
13293
13294 int32_t readcomboaliasfile_to_location(PACKFILE *f, int32_t start)
13295 {
13296 dword section_version=0;
13297 dword section_cversion=0;
13298 int32_t zversion = 0;
13299 int32_t zbuild = 0;
13300
13301 if(!p_igetl(&zversion,f))
13302 {
13303 return 0;
13304 }
13305 if(!p_igetl(&zbuild,f))
13306 {
13307 return 0;
13308 }
13309 if(!p_igetw(&section_version,f))
13310 {
13311 return 0;
13312 }
13313 if(!p_igetw(&section_cversion,f))
13314 {
13315 return 0;
13316 }
13317 al_trace("readcomboaliasfile_to_location section_version: %d\n", section_version);
13318 al_trace("readcomboaliasfile_to_location section_cversion: %d\n", section_cversion);
13319
13320 if ( zversion > ZELDA_VERSION )
13321 {
13322 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13323 return 0;
13324 }
13325 else if ( ( section_version > V_COMBOALIASES ) || ( section_version == V_COMBOALIASES && section_cversion > CV_COMBOALIASES ) )
13326 {
13327 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d) subversion (%d)\n", section_version, section_cversion);
13328 return 0;
13329
13330 }
13331 else
13332 {
13333 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13334 }
13335
13336 int32_t index = 0;
13337 int32_t count = 0;
13338 int32_t count2 = 0;
13339 byte tempcset = 0;
13340 word tempword = 0;
13341
13342
13343 //tile id
13344 if(!p_igetl(&index,f))
13345 {
13346 return 0;
13347 }
13348 al_trace("Reading tile: index(%d)\n", index);
13349
13350 //tile count
13351 if(!p_igetl(&count,f))
13352 {
13353 return 0;
13354 }
13355 al_trace("Reading tile: count(%d)\n", count);
13356
13357
13358 combo_alias temp_alias;
13359 memset(&temp_alias, 0, sizeof(temp_alias));
13360
13361 for ( int32_t tilect = 0; tilect < count; tilect++ )
13362 {
13363 memset(&temp_alias, 0, sizeof(temp_alias));
13364 if(!p_igetw(&temp_alias.combo,f))
13365 {
13366 return 0;
13367 }
13368
13369 if(!p_getc(&temp_alias.cset,f))
13370 {
13371 return 0;
13372 }
13373
13374 int32_t count2 = 0;
13375
13376 if(!p_igetl(&count2,f))
13377 {
13378 return 0;
13379 }
13380
13381 if(!p_getc(&temp_alias.width,f))
13382 {
13383 return 0;
13384 }
13385
13386 if(!p_getc(&temp_alias.height,f))
13387 {
13388 return 0;
13389 }
13390
13391 if(!p_getc(&temp_alias.layermask,f))
13392 {
13393 return 0;
13394 }
13395 //These values are flexible, and may differ in size, so we delete them
13396 //and recreate them at the correct size on the pointer.
13397 temp_alias.combos.clear();
13398 temp_alias.csets.clear();
13399
13400 for(int32_t k=0; k<count2; k++)
13401 {
13402 if(!p_igetw(&tempword,f))
13403 {
13404 return 0;
13405 }
13406 else
13407 {
13408 temp_alias.combos[k] = tempword;
13409 }
13410 }
13411
13412 for(int32_t k=0; k<count2; k++)
13413 {
13414 if(!p_getc(&tempcset,f))
13415 {
13416 return 0;
13417 }
13418 else
13419 {
13420 temp_alias.csets[k] = tempcset;
13421 }
13422 }
13423
13424 if ( start+(tilect) < MAXCOMBOALIASES )
13425 {
13426 memcpy(&combo_aliases[start+(tilect)],&temp_alias,sizeof(temp_alias));
13427 }
13428 }
13429 return 1;
13430 }
13431 int32_t writecomboaliasfile(PACKFILE *f, int32_t index, int32_t count)
13432 {
13433 al_trace("Running writecomboaliasfile\n");
13434 dword section_version=V_COMBOALIASES;
13435 dword section_cversion=CV_COMBOALIASES;
13436 int32_t zversion = ZELDA_VERSION;
13437 int32_t zbuild = VERSION_BUILD;
13438
13439 if(!p_iputl(zversion,f))
13440 {
13441 return 0;
13442 }
13443 if(!p_iputl(zbuild,f))
13444 {
13445 return 0;
13446 }
13447 if(!p_iputw(section_version,f))
13448 {
13449 return 0;
13450 }
13451
13452 if(!p_iputw(section_cversion,f))
13453 {
13454 return 0;
13455 }
13456
13457 //start tile id
13458 if(!p_iputl(index,f))
13459 {
13460 return 0;
13461 }
13462
13463 //count
13464 if(!p_iputl(count,f))
13465 {
13466 return 0;
13467 }
13468
13469 for ( int32_t tilect = 0; tilect < count; tilect++ )
13470 {
13471
13472 if(!p_iputw(combo_aliases[index+(tilect)].combo,f))
13473 {
13474 return 0;
13475 }
13476
13477 if(!p_putc(combo_aliases[index+(tilect)].cset,f))
13478 {
13479 return 0;
13480 }
13481
13482 int32_t count2 = ((combo_aliases[index+(tilect)].width+1)*(combo_aliases[index+(tilect)].height+1))*(comboa_lmasktotal(combo_aliases[index+(tilect)].layermask)+1);
13483
13484 if(!p_iputl(count2,f))
13485 {
13486 return 0;
13487 }
13488 al_trace("Write`, Combo alias count is: %d\n", count2);
13489
13490 if(!p_putc(combo_aliases[index+(tilect)].width,f))
13491 {
13492 return 0;
13493 }
13494
13495 if(!p_putc(combo_aliases[index+(tilect)].height,f))
13496 {
13497 return 0;
13498 }
13499
13500 if(!p_putc(combo_aliases[index+(tilect)].layermask,f))
13501 {
13502 return 0;
13503 }
13504
13505 for(int32_t k=0; k<count2; k++)
13506 {
13507 if(!p_iputw(combo_aliases[index+(tilect)].combos[k],f))
13508 {
13509 return 0;
13510 }
13511 }
13512
13513 for(int32_t k=0; k<count2; k++)
13514 {
13515 if(!p_putc(combo_aliases[index+(tilect)].csets[k],f))
13516 {
13517 return 0;
13518 }
13519 }
13520 }
13521
13522 return 1;
13523
13524 }
13525